Auto-Squeeze-Nachtsperre von 0-7 auf 3-6 Uhr verkuerzt (User-Vorgabe)
Gemessen (backtest_cost_gate.py, Teil 2): es gibt KEINE toten Stunden - alle 24 Stunden sind in beiden Halbjahren positiv, keine ist beidhaelftig negativ. Std 0 ist sogar die staerkste des Tages (OeR +1,48/+1,51) und lag im alten Gate. Jedes Fenster kostet also Ertrag; die Sperre kauft ausschliesslich Beaufsichtigungs-Ruhe. Gewaehlt wurde deshalb nach PREIS, nicht nach Edge: 3-6 ist das guenstigste Fenster mit noch >=4 h Schutz (SigmaR -12,5/-62,9 gegen -42,4/-242,6 bei 0-7 = ~27 %). Freigegeben: 0, 1, 2, 7 Uhr. Die 4-h-Untergrenze ist gesetzt, nicht gemessen. Umsetzung: neues [trading] auto_squeeze_night_hours (Default 3,4,5,6, leer = aus), genutzt von _check_auto_squeeze und _check_auto_signal. _SQUEEZE_NIGHT bleibt als STATISTISCHE Nacht-Definition fuer Entry-Checkliste und B4-Monitor - dort gilt die Kostenfalle weiter und der Altdaten-Vergleich bleibt stabil. 7 Parse-Faelle getestet (Default, fehlender Schluessel, leer, Muell, Rueckwaerts-Kompatibilitaet). Live verifiziert am NEUEN Snapshot-Feld squeeze_night_hours = 3,4,5,6 und am Startup-Log; genau eine Instanz auf 8000. Offen und als Reminder hinterlegt: der Backtest modelliert keine Slippage, und die freigegebenen Stunden liegen in der duennsten Liquiditaet. Nach 15 Squeeze-Trades aus 0/1/2/7 Uhr gegen die Erwartung pruefen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
cdee6eced7
commit
1c9bb34095
+42
-10
@@ -77,7 +77,13 @@ _PAT_W = 0.25 # Verdict-Gewicht der Chartmuster-Stimme (bestaetigt; `form
|
||||
# letzten 4.000 `verdict_votes`: Median der uebrigen Gewichte 4,50
|
||||
# → 0,25/(4,50+0,25) = 5,3 % Anteil an der Bias-Nadel (vorher 1,0
|
||||
# = 18,2 %). Begruendung + Beleglage bei der Stimme in `_verdict`.
|
||||
_SQUEEZE_NIGHT = (0, 1, 2, 3, 4, 5, 6, 7) # Auto-Squeeze-Nacht-Sperre (Kostenfalle)
|
||||
_SQUEEZE_NIGHT = (0, 1, 2, 3, 4, 5, 6, 7) # STATISTISCHE Nacht-Definition
|
||||
# ⚠ `_SQUEEZE_NIGHT` ist NICHT mehr das Entry-Gate — es bleibt die Definition von
|
||||
# „Nacht" für die Entry-Checkliste (dort gilt die Kostenfalle: über ALLE Nacht-Bars
|
||||
# 0,333×ATR) und für den Tag/Nacht-Split im B4-Monitor (damit der Vergleich mit den
|
||||
# Altdaten stabil bleibt). Welche Stunden der Auto-Squeeze wirklich AUSSETZT, steht
|
||||
# in `[trading] auto_squeeze_night_hours` (s. `_squeeze_night_hours`).
|
||||
_SQUEEZE_NIGHT_DEFAULT = "3,4,5,6" # gemessen günstigstes ≥4-h-Fenster, s. u.
|
||||
_SQUEEZE_SR_COOLDOWN_S = 180.0 # nach S/R-Close kein Auto-Squeeze in GLEICHER Richtung
|
||||
# (sonst Close-„Level hält" vs. Entry-„Level bricht"-
|
||||
# Roundtrip in 1 s; 2026-07-17)
|
||||
@@ -310,6 +316,16 @@ class TradingEngine:
|
||||
# auto_squeeze=true` aktiviert. Dedup über (dir, level) des Ausbruchs.
|
||||
self._auto_squeeze = self.cfg["trading"].get("auto_squeeze", "false").lower() == "true"
|
||||
self._squeeze_skip_night = self.cfg["trading"].get("auto_squeeze_skip_night", "true").lower() == "true"
|
||||
# ── WELCHE Stunden ausgesetzt werden (2026-08-05, gemessen `backtest_cost_gate.py`).
|
||||
# War fest 0–7. Die Messung zeigt: KEINE Stunde ist in beiden Halbjahren negativ —
|
||||
# es gibt keine „toten Stunden". Jedes Fenster kostet also Ertrag; die Sperre kauft
|
||||
# ausschließlich Beaufsichtigungs-Ruhe. 3–6 Uhr ist das günstigste Fenster mit noch
|
||||
# ≥4 h Schutz: Preis ΣR −12,5/−62,9 R gegen −42,4/−242,6 bei 0–7 (≈ 27 %).
|
||||
# Leere Liste = wirkt wie `auto_squeeze_skip_night=false`.
|
||||
self._squeeze_night_hours = tuple(
|
||||
int(x) for x in str(self.cfg["trading"].get(
|
||||
"auto_squeeze_night_hours", _SQUEEZE_NIGHT_DEFAULT)).split(",")
|
||||
if x.strip().isdigit() and 0 <= int(x) <= 23)
|
||||
# Stop-&-Reverse nur, wenn explizit an (Default aus) — der Reverse ist unbelegt;
|
||||
# der flat-Entry bleibt davon unberührt (der validierte Teil).
|
||||
self._squeeze_reverse = self.cfg["trading"].get("auto_squeeze_reverse", "false").lower() == "true"
|
||||
@@ -564,6 +580,9 @@ class TradingEngine:
|
||||
self._threads.append(t)
|
||||
|
||||
log.info(f"Engine gestartet · Symbol {self.data.symbol} · TF {saved_tf}")
|
||||
log.info("Auto-Squeeze-Nachtsperre: " + (
|
||||
", ".join(f"{h}:00" for h in self._squeeze_night_hours)
|
||||
if (self._squeeze_skip_night and self._squeeze_night_hours) else "AUS"))
|
||||
return True
|
||||
|
||||
def stop(self):
|
||||
@@ -1047,12 +1066,15 @@ class TradingEngine:
|
||||
if d not in ("LONG", "SHORT") or lvl is None:
|
||||
return
|
||||
sig = (d, round(float(lvl), 2))
|
||||
# ── Dead-Hour-Guard (0–7 Uhr Berlin, 2026-07-17): nachts KOMPLETT inaktiv —
|
||||
# kein Entry UND kein Reverse (der Squeeze ist in dünner Nacht-Liquidität in
|
||||
# BEIDE Richtungen unzuverlässig; die 3 Nacht-Squeezes waren die ganze
|
||||
# Verlustquelle). Setzt keine Dedup-Marker → feuert nach 08:00, falls noch
|
||||
# aktiv. `auto_squeeze_skip_night=false` schaltet aus.
|
||||
if self._squeeze_skip_night and datetime.now(_BERLIN).hour in _SQUEEZE_NIGHT:
|
||||
# ── Nacht-Guard (Fenster aus `auto_squeeze_night_hours`, Default 3–6 Uhr
|
||||
# Berlin; war bis 2026-08-05 fest 0–7): kein Entry UND kein Reverse. Setzt
|
||||
# keine Dedup-Marker → feuert nach dem Fenster, falls noch aktiv.
|
||||
# ⚠ Der Guard ist NICHT ertrags-begründet: gemessen ist keine Nachtstunde in
|
||||
# beiden Halbjahren negativ, jede geblockte Stunde KOSTET (`backtest_cost_
|
||||
# gate.py`). Er kauft Beaufsichtigungs-Ruhe — 3–6 ist die günstigste Variante
|
||||
# davon. `auto_squeeze_skip_night=false` (oder leere Liste) schaltet ihn aus.
|
||||
if (self._squeeze_skip_night
|
||||
and datetime.now(_BERLIN).hour in self._squeeze_night_hours):
|
||||
return
|
||||
# ── News-Blackout (Handbuch-Regel, NICHT gemessen): 15 min um ein
|
||||
# High-Impact-Event (FOMC/NFP/CPI/EIA/OPEC) kein autonomer Entry. Setzt
|
||||
@@ -1179,9 +1201,14 @@ class TradingEngine:
|
||||
conf = sig_snap.get("conf_pct") or 0
|
||||
if conf < self._auto_signal_min_conf:
|
||||
return # zu schwach (Dedup NICHT setzen)
|
||||
# Nacht-Sperre (gemessene Kostenfalle 0–7 Uhr Berlin) — kein Dedup-Marker,
|
||||
# damit das Signal nach 08:00 noch feuern kann, falls es dann noch steht.
|
||||
if self._auto_signal_skip_night and datetime.now(_BERLIN).hour in _SQUEEZE_NIGHT:
|
||||
# Nacht-Sperre — dasselbe Fenster wie beim Auto-Squeeze
|
||||
# (`auto_squeeze_night_hours`, Default 3–6). Kein Dedup-Marker, damit das
|
||||
# Signal danach noch feuern kann, falls es dann noch steht.
|
||||
# ⚠ Anders als beim Squeeze ist die Kostenfalle für die WELLEN-Population
|
||||
# gemessen einschlägig (alle Nacht-Bars 0,333×ATR) — hier ist der Guard also
|
||||
# auch ertrags-begründet. Der Pfad ist ohnehin aus (`auto_signal=false`).
|
||||
if (self._auto_signal_skip_night
|
||||
and datetime.now(_BERLIN).hour in self._squeeze_night_hours):
|
||||
return
|
||||
# News-Blackout (s. `_check_auto_squeeze`) — kein Dedup-Marker.
|
||||
if self.calendar.blackout():
|
||||
@@ -3330,6 +3357,11 @@ class TradingEngine:
|
||||
"sr_close_pbreak": self._sr_close_pbreak,
|
||||
"sr_close_count": self._sr_close_count,
|
||||
"auto_squeeze": self._auto_squeeze,
|
||||
# Nacht-Fenster mitliefern: nach `restart_server.bat` ist ein NEUES
|
||||
# Snapshot-Feld der einzige verlässliche Beleg, dass wirklich der neue
|
||||
# Python-Code läuft (der Batch hat schon 2× still nicht neu gestartet).
|
||||
"squeeze_night_hours": list(self._squeeze_night_hours)
|
||||
if self._squeeze_skip_night else [],
|
||||
"squeeze_entry_count": self._squeeze_entry_count,
|
||||
"auto_signal": self._auto_signal,
|
||||
"auto_signal_min_conf": self._auto_signal_min_conf,
|
||||
|
||||
Reference in New Issue
Block a user