Auto-Signal-Entry + 15-Min-Regel (User-Wunsch, gegen die Messung, mit besten Params)
User will Auto-Eroeffnung bei Empfehlung trotz negativem Backtest -> gebaut, Default AUS, mit den GEMESSEN besten Parametern statt geratenen: Entry (_check_auto_signal, [trading] auto_signal=false): - min_conf=75 + Nacht-Sperre = beste Kombi (H1 -0.053 mildester Verlust, H2 +0.141 bestes Netto). NICHT weil "mehr Konfidenz besser" -- conf_pct ist unkalibriert, 75 ist empirisch. - Nur FLAT, 1x je Signal-Episode (Dedup, re-armt bei WARTEN/Flip), kein Nachkauf, kein Drehen einer Gegen-Position; erbt Circuit-Breaker + beide Cooldowns. - Setup-Tag AUTOSIG_<dir> -> in der DB separierbar fuer B4-Monitor. - Toggle POST /api/autosignal, Button "SIG" (bernstein = gemessen nicht tragfaehig), neustart-fest via runtime_state.json. 15-Min-Regel (_check_adverse15, adverse_15min_atr=0.5): - Schwelle GEMESSEN kalibriert: "sobald im Minus" ist die SCHLECHTESTE Variante (WR 39->31%, Netto -0.067 vs +0.026 ohne); 0.5xATR ist die beste (H1 -0.111 -> -0.079). Netto bringt die Regel ~nichts = Regime-Schutz. - Nur BOT-eroeffnete Trades (_bot_open_ticket) -- manuelle Diskretion bleibt. - 1x je Ticket geprueft, Startup-Grace respektiert, closed_by=adverse15. Verifiziert: 18 synthetische Szenarien (9 Entry + 9 Adverse) alle korrekt; Live-Neustart ohne Loop-Fehler, Toggle + Persistenz geprueft. v=119. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
d40616fbeb
commit
2996eddd7e
+30
-7
@@ -50,6 +50,7 @@ _TIMESTOP = 24 # Time-Stop: 120 min = 24 M5-Bars in Phase „Init"
|
||||
_MAXH = 288 # Sim-Horizont (24 h auf M5)
|
||||
_ATRMIN = 0.06 # ATR-Floor wie live (_ATR_MIN in trailing.py)
|
||||
_NIGHT = (0, 1, 2, 3, 4, 5, 6, 7) # Berlin-Stunden = gemessene Kostenfalle
|
||||
_ADV_BARS = 3 # 15-Min-Regel: 3 M5-Bars = 15 min nach Entry prüfen
|
||||
_HTF_N = 6 # 6 M5-Bars = 1 M30-Bar
|
||||
_H1_N = 12 # 12 M30-Bars … (H1 = 12 M5-Bars)
|
||||
|
||||
@@ -110,9 +111,13 @@ def _htf_signs(H, L, C, step):
|
||||
return out
|
||||
|
||||
|
||||
def _sim(entry, d, atr, H, L, C, j0):
|
||||
def _sim(entry, d, atr, H, L, C, j0, adv15=None):
|
||||
"""Live-Exit-Modell. Rückgabe R = Profit/ATR (brutto, ohne Kosten).
|
||||
Phasen-Ratsche wie live: Time-Stop greift nur, solange nie Trail-Start erreicht."""
|
||||
Phasen-Ratsche wie live: Time-Stop greift nur, solange nie Trail-Start erreicht.
|
||||
|
||||
`adv15` = 15-Minuten-Regel (User-Wunsch 2026-07-30): steht der Trade nach
|
||||
_ADV_BARS (3 M5-Bars = 15 min) mehr als adv15×ATR im Minus → schließen.
|
||||
None = aus. adv15=0.0 bedeutet „schließen wenn überhaupt im Minus"."""
|
||||
eff = entry - d * _SL_ATR * atr
|
||||
hw = entry
|
||||
trail_started = False
|
||||
@@ -125,6 +130,11 @@ def _sim(entry, d, atr, H, L, C, j0):
|
||||
exit_px = eff; break
|
||||
hw = max(hw, hi) if d > 0 else min(hw, lo)
|
||||
prof = (C[j] - entry) * d
|
||||
# 15-Minuten-Regel: EINMALIGE Prüfung genau beim Bar _ADV_BARS nach Entry.
|
||||
# Läuft der Trade dann gegen mich → raus (Einstieg war falsch).
|
||||
if adv15 is not None and (j - j0) == _ADV_BARS - 1:
|
||||
if prof <= -adv15 * atr:
|
||||
exit_px = C[j]; break
|
||||
if prof >= _TRAIL_ON * atr:
|
||||
trail_started = True
|
||||
cand = hw - d * _TRAIL * atr
|
||||
@@ -149,7 +159,7 @@ def _rep(name, Rs, ref=None):
|
||||
return s / n
|
||||
|
||||
|
||||
def scan(bars, H, L, C, SP, A, HTF, H1, EF, ES, w, lo_i, hi_i, min_conf, skip_night):
|
||||
def scan(bars, H, L, C, SP, A, HTF, H1, EF, ES, w, lo_i, hi_i, min_conf, skip_night, adv15=None):
|
||||
"""Sequentielle 1-Positions-Simulation: nimmt das ERSTE Signal, wenn flat."""
|
||||
Rs = []
|
||||
i = max(lo_i, _EMA_SLOW + 20)
|
||||
@@ -172,7 +182,7 @@ def scan(bars, H, L, C, SP, A, HTF, H1, EF, ES, w, lo_i, hi_i, min_conf, skip_ni
|
||||
d = 1 if sig == "LONG" else -1
|
||||
entry = C[i]
|
||||
cost = (SP[i] if SP[i] > 0 else 0.0225) / atr
|
||||
R = _sim(entry, d, atr, H, L, C, i + 1) - cost
|
||||
R = _sim(entry, d, atr, H, L, C, i + 1, adv15) - cost
|
||||
Rs.append(R)
|
||||
# nach dem Trade weiterspringen: der Exit fand irgendwo in [i+1, i+_MAXH]
|
||||
# statt — konservativ mit dem Time-Stop-Fenster weiterrücken (kein Overlap)
|
||||
@@ -215,8 +225,17 @@ def main():
|
||||
print("=" * 92)
|
||||
|
||||
verdict = {}
|
||||
# 15-Minuten-Regel (User-Wunsch): welche Schwelle ist die beste? Basis =
|
||||
# Konf>=55 + Nacht-Sperre, damit nur die Regel selbst variiert.
|
||||
ADV = [(None, "OHNE 15-Min-Regel (Basis)"), (0.0, "15min raus wenn im Minus"),
|
||||
(0.15, "15min raus wenn < -0,15xATR"), (0.3, "15min raus wenn < -0,3xATR"),
|
||||
(0.5, "15min raus wenn < -0,5xATR"), (0.8, "15min raus wenn < -0,8xATR")]
|
||||
for label, lo, hi in (("H1 (alt)", 0, mid), ("H2 (neu)", mid, N)):
|
||||
print(f"\n{label}:")
|
||||
print(f"\n{label} — 15-MIN-REGEL (Basis Konf>=55 + Nacht-Sperre):")
|
||||
for a, alab in ADV:
|
||||
Rs = scan(bars, H, L, C, SP, A, HTF, H1, EF, ES, w, lo, hi, 55, True, a)
|
||||
verdict.setdefault(("adv", a), []).append(_rep(alab, Rs))
|
||||
print(f"\n{label} — Konfidenz-Achse (ohne 15-Min-Regel):")
|
||||
for mc in (55, 65, 70, 75):
|
||||
for night in (False, True):
|
||||
tag = f"Konf>={mc}" + (" · Nacht-Sperre" if night else "")
|
||||
@@ -227,7 +246,8 @@ def main():
|
||||
print("\n" + "=" * 92)
|
||||
print(" URTEIL (trägt nur, wenn ØR in BEIDEN Hälften > 0 UND im Squeeze-Band):")
|
||||
any_ok = False
|
||||
for (mc, night), vals in sorted(verdict.items()):
|
||||
for key, vals in sorted(verdict.items(), key=lambda kv: str(kv[0])):
|
||||
mc, night = key
|
||||
if len(vals) != 2 or any(v is None for v in vals):
|
||||
continue
|
||||
ok = all(v > 0 for v in vals)
|
||||
@@ -235,7 +255,10 @@ def main():
|
||||
mark = "✅ TRÄGT" if (ok and band) else ("⚠ positiv, unter Squeeze-Band" if ok else "❌ fällt durch")
|
||||
if ok and band:
|
||||
any_ok = True
|
||||
tag = f"Konf>={mc}" + (" +Nacht-Sperre" if night else "")
|
||||
if mc == "adv":
|
||||
tag = "15Min-Regel " + (str(night) if night is not None else "AUS")
|
||||
else:
|
||||
tag = f"Konf>={mc}" + (" +Nacht-Sperre" if night else "")
|
||||
print(f" {tag:<28} H1 ØR {vals[0]:+.3f} · H2 ØR {vals[1]:+.3f} {mark}")
|
||||
print("\n " + ("→ mindestens eine Variante trägt: Einbau vertretbar (klein starten, B4-Monitor)."
|
||||
if any_ok else
|
||||
|
||||
Reference in New Issue
Block a user