#!/usr/bin/env python3
"""Volatilitäts-Squeeze-Breakout (B2, User-Idee 'Breakouterkennung'):
Struktureller Ausbruch aus einer KOMPRESSION — NICHT aus dem EMA-Trend.
Setup: die Spanne der letzten N Bars (Box) ist eng relativ zum ATR (Squeeze);
danach bricht der Kurs k×ATR über/unter die Box → Einstieg in Ausbruchsrichtung.
Exit = live-Modell (SL 2,0×ATR + Trailing 1,5, Breakeven 1,3), pessimistisch.
Kosten = echter Bar-Spread/ATR (Ø ~0,265). 2 Halbjahre. R = Profit/ATR.

Kernfrage (B3): Trägt der SQUEEZE-Filter netto in BEIDEN Hälften — schlägt er den
Ausbruch aus einer BELIEBIGEN Box (ohne Kompression)? Sonst raus.
"""
import sys
import MetaTrader5 as mt5

_MAXH = 288; _ATRMIN = 0.12
_N   = 12      # Box-Länge (Bars) = 1 h auf M5
_W   = 24      # Fenster nach der Box, in dem der Breakout erfolgen muss (2 h)
_COOL = 12     # Cooldown nach einem Trade (Bars) gegen Überlappung
_K   = 0.1     # Ausbruch k×ATR über/unter die Box-Grenze


# ⚠⚠ DIE MECHANIK LIEGT SEIT 2026-08-07 IN `core/squeeze_scan.py`.
# Grund: `core/engine.py` und `weekly_review.py` haben sie von HIER importiert —
# LIVE-Code, der an einem Backtest-Skript haengt, und die Live-Parameter wurden
# ueber MUTIERTE Modul-Globale (`BQ._N = ...`) eingeschleust. Beides ist behoben.
# Hier bleiben nur duenne Weiterleitungen, damit es EINE Implementierung gibt und
# nicht zwei, die auseinanderdriften — der Fehler, den dieses Projekt bei
# `sim_run`/`_ema_series` (Kopien in >=6 Skripten) schon einmal gemacht hat.
# ⚠ Die Zahlen dieses Backtests bleiben unveraendert: bitgenau geprueft in
# `tests/test_squeeze_scan.py` (500 synthetische Kursreihen).
from core.squeeze_scan import atr_series as _core_atr
from core.squeeze_scan import exit_legacy as _core_exit
from core.squeeze_scan import scan as _core_scan


def _atr_series(H, L, C, p=14):
    return _core_atr(H, L, C, p)


def sim(entry, d, atr, H, L, C, j0, sl_atr=2.0, trail=1.5, trail_on=0.3, be_on=1.3):
    return _core_exit(entry, d, atr, H, L, C, j0, sl_atr=sl_atr, trail=trail,
                      trail_on=trail_on, be_on=be_on, max_hold=_MAXH)


def rep(name, Rs):
    if not Rs: print(f"  {name:<32} -"); return
    n = len(Rs); w = sum(1 for x in Rs if x > 0); s = sum(Rs)
    up = sum(x for x in Rs if x > 0); dn = -sum(x for x in Rs if x < 0)
    pf = up/dn if dn > 0 else 9.99
    print(f"  {name:<32} Trades={n:>4} Treffer={100*w/n:>3.0f}% "
          f"ØR={s/n:+.3f} PF={pf:.2f} ΣR={s:+.0f}")


def scan(H, L, C, A, SP, point, lo_i, hi_i, squeeze_mult):
    """Weiterleitung auf `core.squeeze_scan.scan` mit den Modul-Globalen dieses
    Skripts als Parameter (`main()` variiert `_N`/`_K` beim Sweep)."""
    return _core_scan(H, L, C, A, SP, point, lo_i, hi_i, squeeze_mult,
                      box_n=_N, k=_K, atr_min=_ATRMIN, fenster=_W,
                      cooldown=_COOL, max_hold=_MAXH)


def main():
    n = int(sys.argv[1]) if len(sys.argv) > 1 else 80000
    mt5.initialize()
    sym = None
    for c in ("SpotCrude", "USOIL", "WTI", "XTIUSD"):
        if mt5.symbol_info(c): sym = c; break
    bars = mt5.copy_rates_from_pos(sym, mt5.TIMEFRAME_M5, 0, n+_MAXH+30)
    si = mt5.symbol_info(sym); point = si.point
    mt5.shutdown()
    H = [float(b["high"]) for b in bars]; L = [float(b["low"]) for b in bars]
    C = [float(b["close"]) for b in bars]; SP = [float(b["spread"])*point for b in bars]
    A = _atr_series(H, L, C)
    N = len(C); mid = N//2
    print("="*88)
    print(f"  Volatilitäts-Squeeze-Breakout — {sym} M5  ({N} Bars · Box={_N} · Ausbruch={_K}×ATR)")
    print(f"  Exit=live(SL2,0/Trail1,5/BE1,3) · Kosten=Bar-Spread/ATR · 2 Halbjahre")
    print("="*88)
    for label, lo, hi in (("H1 (alt)", 0, mid), ("H2 (neu)", mid, N)):
        print(f"\n{label}:")
        _, any_R = scan(H, L, C, A, SP, point, lo, hi, 99.0)
        rep("Ausbruch OHNE Squeeze-Filter", any_R)
        for sm in (2.5, 2.0, 1.5):
            sq_R, _ = scan(H, L, C, A, SP, point, lo, hi, sm)
            rep(f"Squeeze  Box<={sm}×ATR", sq_R)
    print(f"\n  Squeeze trägt nur, wenn ØR & PF in BEIDEN Hälften > 'ohne Filter' UND ØR netto > 0.")

if __name__ == "__main__":
    main()
