Slippage vs Vola-Regime gemessen + Ziel-Erreichbarkeit gebaut (v=154)
MESSUNG (analyze_slippage_vola.py, 337 SL-Closes): die Exit-Slippage steigt MONOTON ueber alle vier Delta-ATR-Quartile: 0,39-0,91 Schaetzer 0,0200 $ 0,91-1,08 0,0390 $ 1,08-1,26 0,0645 $ 1,26-2,39 0,0839 $ Faktor 4,19x Mechanismus stimmig: die Slip-RATE bleibt flach (20-23 %), die GROESSE waechst (0,094 -> 0,396 $). Es rutscht nicht oefter, sondern weiter. ABER: der Bootstrap auf die DIFFERENZ oben-unten ergibt [-0,012 ... +0,183] - enthaelt die Null. Bei n=85 je Quartil NICHT statistisch belegt. Meine vorab fixierte Regel (Faktor >=2 UND monoton) war damit unterspezifiziert - sie haette ein Konfidenzintervall verlangen muessen. Konsequenz: gebaut als reiner HINWEIS im Kosten-Gate, kein Gate, und die Beschriftung sagt "historisch ~4x hoeher", nicht "belegt". ZIEL-ERREICHBARKEIT (Vorschlag 3, Decay-Clock): reine Geometrie auf dem kalibrierten Kegel - passt das Gegenlevel noch in das 80-%-Band des jeweiligen Horizonts? Live: Ziel 77,784 (0,401 $) liegt im 120'-Kegel, nicht im 30'/60'. Die im Vorschlag mitgedachte Annahme "je laenger, desto eher bricht es" ist BEWUSST NICHT eingebaut - sie ist nicht belegt (Touch-Zahl: umgekehrtes U auf 4 Live-Tagen, im Backtest +0,010 AUC, nach dem Nachtrainieren gar nichts mehr). Umsetzung ohne zweiten MT5-Fetch: _vola_regime puffert den ATR_M15 aus dem ohnehin laufenden Turn-Fetch (deque, ~5 h). Kaltstart liefert datr=null statt zu raten - live verifiziert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
44955bf70a
commit
e5adfc9757
@@ -3974,6 +3974,43 @@ class TradingEngine:
|
||||
log.debug(f"sr_close_hint: {e}")
|
||||
return None
|
||||
|
||||
def _vola_regime(self, atr15) -> dict | None:
|
||||
"""ΔATR = aktueller ATR_M15 / Median der letzten ~5 h.
|
||||
|
||||
⚠ KEIN zweiter MT5-Fetch: der ATR wird aus dem ohnehin laufenden
|
||||
Turn-Fetch gesammelt (`wave.tf_atr`), hier nur gepuffert. Ein extra
|
||||
Abruf fuer Zahlen, die schon da sind, war beim Konsens-Pfeil der Fehler.
|
||||
|
||||
⚠⚠ BELEGLAGE, ehrlich: gemessen (`analyze_slippage_vola.py`, 337
|
||||
SL-Closes) steigt die Exit-Slippage MONOTON ueber alle vier
|
||||
ΔATR-Quartile — 0,0200 → 0,0390 → 0,0645 → 0,0839 $, Faktor 4,19×.
|
||||
Die Slip-RATE bleibt dabei flach (20–23 %), die GROESSE waechst
|
||||
(0,094 → 0,396 $): es rutscht nicht oefter, sondern weiter.
|
||||
ABER: der Bootstrap auf die DIFFERENZ oben−unten ergibt
|
||||
[−0,012 … +0,183] — **enthaelt die Null**. Bei n≈85 je Quartil ist der
|
||||
Unterschied NICHT statistisch belegt. Deshalb reine ANZEIGE, kein Gate,
|
||||
und die Beschriftung sagt das auch.
|
||||
"""
|
||||
try:
|
||||
if not atr15 or atr15 <= 0:
|
||||
return None
|
||||
buf = getattr(self, "_atr15_buf", None)
|
||||
if buf is None:
|
||||
from collections import deque
|
||||
buf = self._atr15_buf = deque(maxlen=1200) # ~5 h bei 15-s-Takt
|
||||
buf.append(float(atr15))
|
||||
if len(buf) < 200:
|
||||
return {"datr": None, "stufe": None}
|
||||
import statistics as _st
|
||||
med = _st.median(buf)
|
||||
if med <= 0:
|
||||
return {"datr": None, "stufe": None}
|
||||
d = atr15 / med
|
||||
return {"datr": round(d, 2),
|
||||
"stufe": "hoch" if d >= 1.26 else "normal" if d >= 0.91 else "ruhig"}
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _m15_setup(self, market, wave_snap, cone, alignment) -> dict | None:
|
||||
"""SETUP-BEREITSCHAFT auf M15 — der Ersatz für die entfernte Gesamtempfehlung.
|
||||
|
||||
@@ -4044,6 +4081,32 @@ class TradingEngine:
|
||||
"lo": x.get("lo"), "hi": x.get("hi")}
|
||||
for x in b80] or None
|
||||
|
||||
# ── 4b) ZIEL-ERREICHBARKEIT — reine GEOMETRIE auf dem Kegel.
|
||||
# Ziel eines Trades am nahen Level ist das GEGENÜBERLIEGENDE.
|
||||
# Gefragt wird nur: passt dieser Abstand noch in das 80-%-Band
|
||||
# des jeweiligen Horizonts? ⚠ KEINE Bruch-Annahme — die im
|
||||
# Vorschlag mitgedachte „je länger, desto eher bricht es"-Regel
|
||||
# ist gemessen NICHT robust (Touch-Zahl: umgekehrtes U auf 4
|
||||
# Live-Tagen, im Backtest +0,010 AUC und nach dem Nachtrainieren
|
||||
# gar nichts mehr). Hier steckt deshalb nur Arithmetik.
|
||||
if len(zonen) == 2 and bid and b80:
|
||||
nah = min(zonen, key=lambda x: x["gap_atr15"])
|
||||
fern = max(zonen, key=lambda x: x["gap_atr15"])
|
||||
strecke = abs(fern["level"] - bid)
|
||||
out["ziel"] = {
|
||||
"level": fern["level"], "strecke": round(strecke, 3),
|
||||
"horizonte": [{"minutes": x.get("minutes"),
|
||||
"drin": bool(x.get("lo") is not None
|
||||
and x.get("hi") is not None
|
||||
and x["lo"] <= fern["level"] <= x["hi"])}
|
||||
for x in b80],
|
||||
"von": nah["level"]}
|
||||
else:
|
||||
out["ziel"] = None
|
||||
|
||||
# ── 4c) VOLA-REGIME als Slippage-HINWEIS (kein Gate, s. Docstring)
|
||||
out["vola"] = self._vola_regime(atr15)
|
||||
|
||||
# ── 5) VETO — die eigene Bilanz, je Lot (absolute Euro sind bei
|
||||
# wechselnder Positionsgröße ungültig, Lehre vom 04.08.)
|
||||
out["veto"] = alignment or None
|
||||
|
||||
Reference in New Issue
Block a user