"""Die Verhaltens-Behauptungen aus „Ein Fuchs namens Risiko“ auf den EIGENEN
Trades gemessen (User-Auftrag 2026-08-19: "nutze alle Buecher als Ideenquelle").

WARUM AUSGERECHNET DIESES BUCH. Von den sechs Buechern im Verzeichnis ist es das
einzige, dessen Kernaussagen auf der vorhandenen Datenlage **pruefbar** sind:
  Kap. 9  "Der Drang, Verluste zurueckzuholen"   -> Revenge-Trading
  Kap. 11 "Overtrading fuehlt sich an wie Kontrolle"
  Kap. 12 "Revenge Trading und der rote Nebel"
  Kap. 14 "Warum Langeweile profitabel ist"
  Kap. 10 "Warum kleine Verluste gesund sind"
Alle vier sind Aussagen ueber die REIHENFOLGE und den ABSTAND von Trades -- und
genau das steht in `trades` (entry_time, exit_time, pnl, lots).

⚠⚠ WARUM DAS NICHT NUR EIN BUCH-TEST IST. Die Projekt-Zahlen zeigen seit
Wochen in dieselbe Richtung: der MENSCH schlaegt den Bot (+3,20 gegen
-5,85 EUR/Lot), 28 Signal-Eingriffe sind gescheitert, und die einzige
beidhaelftig robuste Aussage ist ein VETO (gegen das Signal -6,60 EUR/Lot).
Der Hebel liegt gemessen im Verhalten -- nur ist das Verhalten selbst hier nie
gemessen worden. Die Entry-Checkliste nennt "nach 2 Losses Session beenden" als
Regel, ohne sie je auf den eigenen Trades geprueft zu haben.

⚠ JE LOT NORMIERT. Absolute Euro sind bei schwankender Positionsgroesse
ungueltig (Lehre 04.08.: der 04.08. sah nur wegen groesserer Lots wie ein
Ausreisser aus). Gerechnet wird `pnl / lots`.

⚠ 95-%-BOOTSTRAP je Zelle. Ein Punktschaetzer ist auf so kleinen Gruppen keine
Aussage. Zellen mit n < 15 werden als zu duenn markiert statt interpretiert.

⚠ GRENZE, vorab benannt: das sind BEOBACHTUNGSdaten, keine Zuweisung. Wer nach
einem Verlust weiterhandelt, waehlt das selbst -- ein Unterschied kann also auch
heissen "in solchen Marktlagen handelt er anders", nicht "der Zeitabstand ist
die Ursache". Die Richtung ist trotzdem verwertbar, weil sie handlungsnah ist.

Aufruf:  python analyze_verhalten.py [tage]
"""
import sqlite3
import sys

from backtest_cost_gate import ci95

DB = "oil_widget_history.db"
MIN_N = 15


def lade(tage):
    c = sqlite3.connect(DB)
    c.row_factory = sqlite3.Row
    q = ("SELECT entry_time, exit_time, pnl, lots FROM trades "
         " WHERE exit_time IS NOT NULL AND pnl IS NOT NULL AND lots > 0 ")
    if tage:
        q += " AND entry_time > strftime('%s','now','-{} days') ".format(int(tage))
    q += " ORDER BY entry_time"
    rows = [dict(r) for r in c.execute(q)]
    c.close()
    for r in rows:
        r["pl"] = r["pnl"] / r["lots"]
    return rows


def zeig(lbl, werte):
    if not werte:
        print("    {:<34} --".format(lbl)); return
    n = len(werte); m = sum(werte) / n
    ci = ci95(werte) if n >= 20 else None
    s = "n={:>4}  {:>5.0f}% Gew.  {:+8.2f} EUR/Lot".format(
        n, 100.0 * sum(1 for x in werte if x > 0) / n, m)
    if ci:
        s += "  [{:+7.2f} .. {:+7.2f}]".format(ci[0], ci[1])
        s += "" if ci[0] * ci[1] > 0 else "  ~0"
    if n < MIN_N:
        s += "   ⚠ zu duenn"
    print("    {:<34} {}".format(lbl, s))


def main():
    tage = int(sys.argv[1]) if len(sys.argv) > 1 else 0
    tr = lade(tage)
    if len(tr) < 50:
        print("zu wenige Trades:", len(tr)); return

    print("=" * 100)
    print("  VERHALTENS-MESSUNG auf {} eigenen Trades{}".format(
        len(tr), "  (letzte {} Tage)".format(tage) if tage else "  (gesamt)"))
    print("  je Lot normiert · 95-%-Bootstrap · Zellen < {} als zu duenn markiert".format(MIN_N))
    print("=" * 100)

    # ---- (1) REVENGE: Abstand zum vorigen EXIT, getrennt nach dessen Ausgang --
    print("\n  (1) REVENGE-TRADING — wie schnell nach dem letzten Ausstieg?")
    print("  " + "-" * 96)
    for nach_verlust in (True, False):
        gr = {"< 5 min": [], "5–30 min": [], "30–120 min": [], "> 2 h": []}
        for a, b in zip(tr, tr[1:]):
            if (a["pnl"] < 0) != nach_verlust:
                continue
            dt = (b["entry_time"] - a["exit_time"]) / 60.0
            if dt < 0:
                continue
            k = ("< 5 min" if dt < 5 else "5–30 min" if dt < 30
                 else "30–120 min" if dt < 120 else "> 2 h")
            gr[k].append(b["pl"])
        print("    nach einem {}:".format("VERLUST" if nach_verlust else "Gewinn"))
        for k, v in gr.items():
            zeig("      " + k, v)

    # ---- (2) VERLUST-SERIE ---------------------------------------------------
    print("\n  (2) VERLUST-SERIE — der wievielte Trade nach wie vielen Verlusten?")
    print("      (Projekt-Regel der Entry-Checkliste: 'nach 2 Losses Session beenden')")
    print("  " + "-" * 96)
    serie = 0
    gr = {0: [], 1: [], 2: [], 3: []}
    for t in tr:
        gr[min(serie, 3)].append(t["pl"])
        serie = serie + 1 if t["pnl"] < 0 else 0
    for k in sorted(gr):
        zeig("      nach {} Verlust{} in Folge".format(k, "" if k == 1 else "en"), gr[k])

    # ---- (3) OVERTRADING / "Langeweile" -------------------------------------
    print("\n  (3) OVERTRADING — der wievielte Trade des Tages?")
    print("  " + "-" * 96)
    tage_d = {}
    for t in tr:
        d = int(t["entry_time"]) // 86400
        tage_d.setdefault(d, []).append(t)
    gr = {"1.–2.": [], "3.–5.": [], "6.–10.": [], "11.+": []}
    tagesbilanz = {"1–3 Trades": [], "4–8": [], "9–15": [], "16+": []}
    for d, ts in tage_d.items():
        for i, t in enumerate(ts, 1):
            k = ("1.–2." if i <= 2 else "3.–5." if i <= 5
                 else "6.–10." if i <= 10 else "11.+")
            gr[k].append(t["pl"])
        n = len(ts)
        kk = ("1–3 Trades" if n <= 3 else "4–8" if n <= 8
              else "9–15" if n <= 15 else "16+")
        tagesbilanz[kk].append(sum(x["pl"] for x in ts))
    for k, v in gr.items():
        zeig("      " + k + " Trade des Tages", v)
    print("\n  (4) „LANGEWEILE IST PROFITABEL“ — TAGESbilanz je Lot nach Handelsmenge")
    print("      (Einheit: Summe EUR/Lot des Tages, n = Anzahl Tage)")
    print("  " + "-" * 96)
    for k, v in tagesbilanz.items():
        zeig("      " + k, v)
    print("=" * 100)


if __name__ == "__main__":
    main()
