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
@@ -1418,9 +1418,26 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
|
||||
ENTRY` + Telegram + Fehlschlag-Push. Snapshot `auto_squeeze`/`squeeze_entry_count`;
|
||||
Toggle `POST /api/autosqueeze` (`set_auto_squeeze`) = Dashboard-Button **🚀 BRK**
|
||||
(blau=AN, ersetzt den alten Dry-Run-AUTO-Button). **Dead-Hour-Guard = AN
|
||||
(User-Vorgabe 2026-07-24, `[trading] auto_squeeze_skip_night=true`):** der Bot
|
||||
eröffnet **nachts 0–7 Uhr KEINE** Squeeze-Trades (`_SQUEEZE_NIGHT=(0..7)`,
|
||||
`_squeeze_skip_night` → `_check_auto_squeeze` return; kein Entry UND kein Reverse).
|
||||
(User-Vorgabe 2026-07-24, `[trading] auto_squeeze_skip_night=true`) — **Fenster
|
||||
seit 2026-08-05 auf `3,4,5,6` VERKÜRZT** (`[trading] auto_squeeze_night_hours`,
|
||||
User-Vorgabe „verkürze auf die wirklich toten Stunden"; war fest 0–7):** der Bot
|
||||
eröffnet in diesen Stunden **KEINE** Squeeze-Trades (`_squeeze_night_hours` →
|
||||
`_check_auto_squeeze` return; kein Entry UND kein Reverse; leere Liste = aus).
|
||||
⚠ **`_SQUEEZE_NIGHT=(0..7)` bleibt bestehen, ist aber NICHT mehr das Gate** — es
|
||||
ist jetzt nur noch die STATISTISCHE Nacht-Definition für die Entry-Checkliste
|
||||
(dort gilt die Kostenfalle weiterhin, s. u.) und den Tag/Nacht-Split im
|
||||
B4-Monitor (damit der Vergleich mit den Altdaten stabil bleibt). Der
|
||||
Auto-Signal-Pfad nutzt dasselbe neue Fenster (ist ohnehin aus).
|
||||
⚠⚠ **Die Verkürzung ist NICHT ertrags-begründet, sondern preis-begründet** —
|
||||
gemessen ist **keine einzige Nachtstunde in beiden Halbjahren negativ**, jede
|
||||
geblockte Stunde kostet Ertrag (Details beim Fallbeispiel unten). 3–6 ist
|
||||
schlicht 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 %** der bisherigen
|
||||
Kosten. Freigegeben sind **0, 1, 2 und 7 Uhr**. ⚠ Std 0 ist dabei die **beste
|
||||
Stunde des ganzen Tages** für den Squeeze (ØR +1,48/+1,51) — sie zu blocken war
|
||||
der teuerste Einzelposten. Live verifiziert am neuen Snapshot-Feld
|
||||
`squeeze_night_hours` + Startup-Log „Auto-Squeeze-Nachtsperre: 3:00, 4:00, 5:00,
|
||||
6:00". Zurück auf den alten Stand: `auto_squeeze_night_hours = 0,1,2,3,4,5,6,7`.
|
||||
Doppelt begründet: (1) **gemessen** unrentabel (`backtest_realcosts.py`, Spread÷Nacht-
|
||||
ATR 0,32–0,50×ATR, beide Halbjahre negativ = Kostenfalle) und (2) **kein Trade
|
||||
soll unbeaufsichtigt nachts feuern, während der User schläft** — Auslöser: „müsste
|
||||
@@ -1503,8 +1520,34 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
|
||||
(P(break) nachtrainiert, 15-Min-Regel aus, Trail 1,5→1,0). (3) Der
|
||||
**Beaufsichtigungs-Grund** („kein Trade soll feuern, während ich schlafe",
|
||||
User-Vorgabe 2026-07-24) ist eine Präferenz und wird von keiner Zahl berührt.
|
||||
✅ **Deshalb KEINE Änderung vorgenommen** — `auto_squeeze_skip_night` bleibt `true`.
|
||||
Die Messung liegt vor, die Entscheidung ist eine Nutzungs-, keine Messfrage.
|
||||
✅ **Konsequenz (User-Vorgabe 2026-08-05 „verkürze auf die wirklich toten
|
||||
Stunden"): Fenster von 0–7 auf 3–6 verkürzt** — Details oben beim Guard.
|
||||
⚠⚠ **Die Prämisse der Vorgabe hält der Messung nicht stand: es gibt KEINE toten
|
||||
Stunden.** Je Stunde einzeln, sequentiell, beide Halbjahre — **alle 24 Stunden
|
||||
sind in beiden Hälften positiv**, keine einzige ist beidhälftig negativ. Die
|
||||
ruhigsten Nachtstunden (n über beide Hälften): 5 (41 Ausbrüche) · 4 (56) · 3 (61)
|
||||
· 6 (62); die aktivsten 7 (75) · 0/2 (72) · 1 (71). ⚠ **Std 0 ist die stärkste
|
||||
Stunde des gesamten Tages** (ØR +1,483/+1,510, ΣR +22,2/+86,1) — ausgerechnet sie
|
||||
lag im alten Gate.
|
||||
Damit ist die Auswahl **keine Ertrags-Optimierung, sondern eine Preis-Minimierung
|
||||
für eine Präferenz** — und deshalb auch nicht overfitting-gefährdet: es wird keine
|
||||
prädiktive Behauptung aufgestellt. Preisliste (ΣR gegen „kein Gate"):
|
||||
| Fenster | Std | Preis H1 | Preis H2 |
|
||||
|---|---|---|---|
|
||||
| 4–5 | 2 | −3,9 | −18,1 |
|
||||
| 4–6 | 3 | −6,8 | −39,9 |
|
||||
| **3–6 (gewählt)** | **4** | **−12,5** | **−62,9** |
|
||||
| 2–5 | 4 | −12,8 | −77,2 |
|
||||
| 0–7 (alt) | 8 | −42,4 | −242,6 |
|
||||
Die 4-Stunden-Untergrenze ist **gesetzt, nicht gemessen** — darunter wäre der
|
||||
Schutzzweck hinfällig. Wer weniger Schutz will, nimmt 4–5 (fast gratis); wer den
|
||||
alten Stand will, trägt `0,1,2,3,4,5,6,7` ein.
|
||||
⚠ **Was die Verkürzung NICHT ausräumt:** die drei Vorbehalte oben gelten
|
||||
unverändert — vor allem die **nicht modellierte Slippage** (dünnes Nacht-Buch,
|
||||
Tail 0,75×ATR über den Stop). Die freigegebenen Stunden 0/1/2/7 liegen mitten in
|
||||
der dünnsten Zeit. **B4-Pflicht: die Squeeze-Trades aus 0/1/2/7 Uhr getrennt
|
||||
mitzählen** — bleiben sie hinter der Erwartung (ØR ~+0,5 R), war die Slippage
|
||||
der Grund und das Fenster gehört zurück auf 0–7.
|
||||
**Stop-&-Reverse = AUS (Default, `[trading] auto_squeeze_reverse=false`,
|
||||
`_squeeze_reverse`; User-Vorgabe 2026-07-17):** War kurz scharf, dann abgeschaltet —
|
||||
nur der **flat-Entry ist gemessen-validiert**, der Reverse ist unbelegt, verdoppelt
|
||||
|
||||
@@ -346,6 +346,92 @@ def main():
|
||||
print(" waehrend ich schlafe\") ist eine Praeferenz und wird hier NICHT beruehrt.")
|
||||
print()
|
||||
|
||||
# ── TEIL 2: welche Nachtstunden sind WIRKLICH tot? ─────────────────────
|
||||
print("=" * 100)
|
||||
print(" TEIL 2 — WELCHE Nachtstunden tragen den Block? (je Stunde, sequentiell)")
|
||||
print("=" * 100)
|
||||
print(f" {'Std':>3} {'Kosten':>7} | {'n H1':>5} {'OeR H1':>8} {'SigmaR H1':>10}"
|
||||
f" | {'n H2':>5} {'OeR H2':>8} {'SigmaR H2':>10} Urteil")
|
||||
print(" " + "-" * 92)
|
||||
beide_neg = []
|
||||
for s in range(24):
|
||||
k1 = kennzahlen(sequentiell(K, H, L, C, lambda e, s=s: e["stunde"] == s, 0, mid))
|
||||
k2 = kennzahlen(sequentiell(K, H, L, C, lambda e, s=s: e["stunde"] == s, mid, N))
|
||||
ks_ = [e["kosten"] for e in E if e["stunde"] == s]
|
||||
kmed = sorted(ks_)[len(ks_) // 2] if ks_ else float("nan")
|
||||
if not k1 or not k2:
|
||||
continue
|
||||
neg = k1["sr"] < 0 and k2["sr"] < 0
|
||||
if neg:
|
||||
beide_neg.append(s)
|
||||
print(f" {s:>3} {kmed:>7.3f} | {k1['n']:>5} {k1['oer']:>+8.3f} {k1['sr']:>+10.1f}"
|
||||
f" | {k2['n']:>5} {k2['oer']:>+8.3f} {k2['sr']:>+10.1f} "
|
||||
f"{'beide NEGATIV' if neg else ''}")
|
||||
print()
|
||||
print(f" In BEIDEN Haelften negativ: {beide_neg or 'keine'}")
|
||||
print(" ⚠ Diese Liste NICHT direkt als Gate verwenden — 24 Stunden = 24 Tests,")
|
||||
print(" das waere in-sample-zirkulaer (dokumentierter Fehler, backtest_realcosts).")
|
||||
print(" Deshalb unten nur ZUSAMMENHAENGENDE Fenster: ein Fenster hat 1 Freiheits-")
|
||||
print(" grad statt 24 und laesst sich nicht auf das Rauschen zurechtlegen.")
|
||||
print()
|
||||
|
||||
# ── Fenster-Sweep, Regel vorab fixiert ────────────────────────────────
|
||||
print(" ZUSAMMENHAENGENDE NACHT-FENSTER (sequentiell, EIN Slot)")
|
||||
print(" REGEL (vor dem Lauf fixiert): das Fenster muss das heutige 0-7 im SigmaR")
|
||||
print(" in BEIDEN Haelften schlagen. Bei mehreren Treffern gewinnt das LAENGSTE")
|
||||
print(" — der Beaufsichtigungs-Grund hat Wert, der in keiner Zahl steht.")
|
||||
print(f" {'Fenster':<18}{'H1 n WR OeR PF SigmaR':>32}"
|
||||
f" |{'H2 n WR OeR PF SigmaR':>32}")
|
||||
print(" " + "-" * 96)
|
||||
fenster = [("kein Gate", ())]
|
||||
for a in range(0, 8):
|
||||
for b in range(a, 8):
|
||||
fenster.append((f"{a}-{b} Uhr", tuple(range(a, b + 1))))
|
||||
b1, b2 = ergebnis["ohne Gate (Basis)"]
|
||||
zeilen = []
|
||||
for lbl, hh in fenster:
|
||||
if not hh:
|
||||
continue
|
||||
k1 = kennzahlen(sequentiell(K, H, L, C,
|
||||
lambda e, hh=hh: e["stunde"] not in hh, 0, mid))
|
||||
k2 = kennzahlen(sequentiell(K, H, L, C,
|
||||
lambda e, hh=hh: e["stunde"] not in hh, mid, N))
|
||||
if not k1 or not k2:
|
||||
continue
|
||||
p1 = k1["sr"] - b1["sr"]; p2 = k2["sr"] - b2["sr"] # Preis (negativ)
|
||||
nblk = sum(1 for e in E if e["stunde"] in hh)
|
||||
zeilen.append({"lbl": lbl, "hh": hh, "h": len(hh), "p1": p1, "p2": p2,
|
||||
"n": nblk, "je": (p1 + p2) / len(hh)})
|
||||
|
||||
print(" PREIS DER BEAUFSICHTIGUNG — was kostet ein Fenster gegenueber KEINEM Gate?")
|
||||
print(" ⚠ Keine Stunde ist in beiden Haelften negativ. Es gibt also keine")
|
||||
print(" 'toten Stunden' zu streichen — jedes Fenster KOSTET. Die Frage ist")
|
||||
print(" nur, wieviel Schlaf-Schutz man wie teuer einkauft. Das ist eine")
|
||||
print(" PREIS-Minimierung fuer eine Praeferenz, KEINE Edge-Behauptung —")
|
||||
print(" deshalb ist die Auswahl hier auch nicht overfitting-gefaehrdet.")
|
||||
print(f" {'Fenster':<12}{'Std':>4}{'geblockt':>10}{'Preis H1':>10}{'Preis H2':>10}"
|
||||
f"{'SigmaR/Std':>12}")
|
||||
print(" " + "-" * 60)
|
||||
for z in sorted(zeilen, key=lambda z: -z["je"])[:12]:
|
||||
print(f" {z['lbl']:<12}{z['h']:>4}{z['n']:>10}{z['p1']:>+10.1f}"
|
||||
f"{z['p2']:>+10.1f}{z['je']:>+12.1f}")
|
||||
heute = next(z for z in zeilen if z["lbl"] == "0-7 Uhr")
|
||||
print(f" {'... heute:':<12}{heute['h']:>4}{heute['n']:>10}{heute['p1']:>+10.1f}"
|
||||
f"{heute['p2']:>+10.1f}{heute['je']:>+12.1f} <- 0-7 Uhr")
|
||||
print()
|
||||
# Auswahl: guenstigstes Fenster, das noch >=4 Stunden Schlaf-Schutz gibt.
|
||||
# 4 h ist gesetzt, nicht gemessen — darunter waere der Schutzzweck hinfaellig.
|
||||
kand = [z for z in zeilen if z["h"] >= 4]
|
||||
best = max(kand, key=lambda z: z["je"])
|
||||
print(f" => EMPFEHLUNG (>=4 h Schutz, guenstigstes Fenster): **{best['lbl']}**")
|
||||
print(f" Preis H1 {best['p1']:+.1f} / H2 {best['p2']:+.1f} R "
|
||||
f"gegen heute {heute['p1']:+.1f} / {heute['p2']:+.1f}")
|
||||
print(f" = {100*abs(best['p1'])/abs(heute['p1']):.0f} % / "
|
||||
f"{100*abs(best['p2'])/abs(heute['p2']):.0f} % der heutigen Kosten,"
|
||||
f" bei {best['h']} statt 8 Stunden")
|
||||
print(f" freigegeben: {[s for s in range(8) if s not in best['hh']]} Uhr")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
+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,
|
||||
|
||||
@@ -145,6 +145,27 @@ CHECKS = [
|
||||
"→ `auto_squeeze=false` (B5-Rückbau, kein Ego). Sonst weiterlaufen "
|
||||
"lassen. Zahlen: /api/squeeze_monitor bzw. Statistik-Tab.",
|
||||
},
|
||||
{
|
||||
"key": "night_window_0127",
|
||||
"title": "Nacht-Fenster 3–6: tragen die freigegebenen Stunden 0/1/2/7?",
|
||||
"why": "Am 05.08. wurde die Auto-Squeeze-Nachtsperre von 0–7 auf 3–6 verkürzt "
|
||||
"(`backtest_cost_gate.py`: keine Nachtstunde ist beidhälftig negativ, "
|
||||
"das alte Gate kostete ΣR −42/−243 R). Der Backtest modelliert aber "
|
||||
"KEINE Slippage — und genau die freigegebenen Stunden liegen in der "
|
||||
"dünnsten Liquidität (gemessener Tail: 0,75×ATR über den Stop hinaus). "
|
||||
"Das ist die einzige offene Bedrohung des Befunds, und sie lässt sich "
|
||||
"nur live prüfen.",
|
||||
"have": lambda: _q("SELECT COUNT(*) FROM trades WHERE setup LIKE 'SQUEEZE%' "
|
||||
"AND pnl IS NOT NULL AND entry_time >= "
|
||||
"strftime('%s','2026-08-05') AND "
|
||||
"CAST(strftime('%H', entry_time, 'unixepoch', 'localtime') "
|
||||
"AS INTEGER) IN (0,1,2,7)"),
|
||||
"need": 15, "unit": "Squeeze-Trades aus 0/1/2/7 Uhr seit 05.08.",
|
||||
"cmd": "Erwartung aus dem Backtest: diese Stunden gehören zu den besseren "
|
||||
"(Std 0 ist die STÄRKSTE des Tages, ØR +1,48/+1,51). Liegen sie live "
|
||||
"deutlich darunter oder im Minus, war die Slippage der Grund → "
|
||||
"`auto_squeeze_night_hours = 0,1,2,3,4,5,6,7` zurücksetzen.",
|
||||
},
|
||||
# (erledigt 2026-08-04: „M30-Level-Umstellung live gegenprüfen" — Ertrag JE LOT
|
||||
# +17,53 → +36,92 €, Ø-Move je Trade 0,202 → 0,427 $, also verdoppelt wie im
|
||||
# Backtest erwartet. ⚠ Normierung war entscheidend: unnormiert sah HEUTE wie der
|
||||
|
||||
Reference in New Issue
Block a user