""" ZARAR TEŞHİSİ — 'yön doğruluğu %58 ama işlem zararda' sorusunu gerçek işlemler üzerinde ayrıştırır. Kullanım (app.py ile aynı klasörde, internet gerekir): python diagnose.py # BTC-USDT 1H 4000 bar, knn_params.json varsa onu kullanır python diagnose.py ETH-USDT 1H 8000 Çıktı: 1) Brüt (komisyonsuz) vs net PnL -> sorun komisyon mu, kenarın kendisi mi? 2) Çıkış dağılımı SL / TP / ZAMAN ve her birinin ort. R'si -> stop gürültüye göre dar mı? 3) Yön doğruluğu (bağımsız sinyaller) + ortalama getiri vs komisyon eşiği 4) Yön / skor / ADX / yapı uyumu / komisyon-R kırılımları -> hangi dilim zarar yazıyor? Hiçbir parametreyi değiştirmez; yalnızca ölçer. """ import os, sys os.environ["APP_NO_LAUNCH"] = "1" import numpy as np import pandas as pd import app from knn_calibrate import fetch_history, summarize, _fmt def block(title, trades, fee): if not trades: print(f" {title:<28} —") return pnl = np.array([t["pnl"] for t in trades]); r = np.array([t["r"] for t in trades]) gross = pnl + 2 * fee gl = abs(pnl[pnl <= 0].sum()) pf = pnl[pnl > 0].sum() / gl if gl > 0 else 99 print(f" {title:<28} n={len(r):<4d} WR=%{(pnl > 0).mean() * 100:4.1f} PF={min(pf, 99):4.2f} " f"brüt/işlem={gross.mean() * 100:+.3f}% net/işlem={pnl.mean() * 100:+.3f}% ort.R={r.mean():+.3f}") def main(): args = [a for a in sys.argv[1:] if not a.startswith("--")] inst = args[0] if args else "BTC-USDT" bar = args[1] if len(args) > 1 else "1H" total = int(args[2]) if len(args) > 2 else 4000 df = fetch_history(inst, bar, total) print(f"{inst} {bar}: {len(df)} bar · kalibrasyon dosyası: {'VAR' if app.KNN_CALIBRATION else 'yok (varsayılanlar)'}") ind = app.compute_indicators(df) A = ind["_arr"] start = app.WARMUP_BARS + app.KNN_MIN_POOL + 12 scores = [app._score_at(ind, i) for i in range(start, len(df))] trades = app.simulate_trades(df, ind, start, scores) fee = app.FEE_PER_SIDE if len(trades) < 5: print("Yeterli işlem yok."); return print("\n1) BRÜT vs NET") block("TÜMÜ", trades, fee) pnl = np.array([t["pnl"] for t in trades]) print(f" toplam komisyon yükü: {2 * fee * 100:.2f}%/işlem · brüt ort. {(pnl + 2 * fee).mean() * 100:+.3f}% " f"-> {'komisyon kenarı yiyor' if (pnl + 2 * fee).mean() > 0 >= pnl.mean() else ('brüt de negatif: kenar yok' if (pnl + 2 * fee).mean() <= 0 else 'net pozitif')}") print("\n2) ÇIKIŞ DAĞILIMI") for why in ("SL", "TP", "ZAMAN"): block(why, [t for t in trades if t["why"] == why], fee) sl_share = np.mean([t["why"] == "SL" for t in trades]) print(f" SL payı %{sl_share * 100:.0f} · ZAMAN çıkışı ort. R {np.mean([t['r'] for t in trades if t['why'] == 'ZAMAN'] or [float('nan')]):+.3f} " f"(ZAMAN çıkışları kârlı ve SL çok ise stop dar)") print("\n3) YÖN DOĞRULUĞU (bağımsız) + büyüklük") acc = app.directional_accuracy(df, start, scores) if acc: print(f" doğruluk %{acc['accuracy'] * 100:.1f} (n={acc['n_signals']}) · ort. yön-ayarlı getiri {acc['mean_ret'] * 100:+.3f}% " f"· komisyon sonrası {acc['net_ret'] * 100:+.3f}%") for k in ("long_side", "short_side"): if acc[k]: print(f" {k:<11} doğruluk %{acc[k]['accuracy'] * 100:.1f} n={acc[k]['n_signals']} ort.getiri {acc[k]['mean_ret'] * 100:+.3f}%") print("\n4) KIRILIMLAR (hangi dilim zarar yazıyor?)") block("LONG", [t for t in trades if t["dir"] > 0], fee) block("SHORT", [t for t in trades if t["dir"] < 0], fee) for lo, hi in ((2, 3), (3, 4), (4, 99)): block(f"|skor| {lo}-{hi if hi < 99 else '+'}", [t for t in trades if lo <= abs(t["score"]) < hi], fee) tr_idx = {id(t): t["signal_i"] for t in trades} adx = lambda t: A["adx"][t["signal_i"]] for lo, hi in ((0, 15), (15, 25), (25, 999)): block(f"ADX {lo}-{hi if hi < 999 else '+'}", [t for t in trades if lo <= adx(t) < hi], fee) block("yapı UYUMLU", [t for t in trades if A["smc_trend"][t["signal_i"]] * t["dir"] > 0], fee) block("yapı TERS/BELİRSİZ", [t for t in trades if A["smc_trend"][t["signal_i"]] * t["dir"] <= 0], fee) fr = lambda t: 2 * fee / (t["sl_atr"] * A["atr"][t["signal_i"]] / A["c"][t["signal_i"]]) for lo, hi in ((0, 0.12), (0.12, 0.25), (0.25, 99)): block(f"komisyon {lo}-{hi if hi < 99 else '+'}R", [t for t in trades if lo <= fr(t) < hi], fee) block("dinamik SL/TP", [t for t in trades if t["dyn"]], fee) block("sabit SL/TP (yedek)", [t for t in trades if not t["dyn"]], fee) print("\nBu çıktıyı yapıştır; hangi kırılım brüt pozitif/net negatifse (komisyon) ve hangisi brüt negatifse (kenar yok) ona göre hedef seçeriz.") if __name__ == "__main__": main()