Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -510,14 +510,17 @@ def make_features(df: pd.DataFrame):
|
|
| 510 |
return f.replace([np.inf, -np.inf], np.nan), atr
|
| 511 |
|
| 512 |
|
| 513 |
-
def _models():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 514 |
return {
|
| 515 |
-
"hgb": HistGradientBoostingClassifier(
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
"et": ExtraTreesClassifier(n_estimators=300, max_depth=6, min_samples_leaf=30,
|
| 519 |
-
max_features=0.5, n_jobs=-1, random_state=42),
|
| 520 |
-
"lr": make_pipeline(StandardScaler(), LogisticRegression(C=0.05, max_iter=500)),
|
| 521 |
}
|
| 522 |
|
| 523 |
|
|
@@ -537,14 +540,14 @@ def _select(Xtr, ftr, k, thr=0.95):
|
|
| 537 |
return keep
|
| 538 |
|
| 539 |
|
| 540 |
-
def _fit_predict(Xtr, ytr, Xte, w=None, ftr=None, k=0, with_train=False):
|
| 541 |
"""Ensemble: HGB + ExtraTrees + Logistic -> olasılık ortalaması.
|
| 542 |
k>0: fold-içi özellik seçimi. with_train: eğitim verisi üzerindeki olasılıkları da döndür (aşırı uyum ölçümü için)."""
|
| 543 |
if k and ftr is not None:
|
| 544 |
sel = _select(Xtr, ftr, k)
|
| 545 |
Xtr, Xte = Xtr[sel], Xte[sel]
|
| 546 |
ps, pt = [], []
|
| 547 |
-
for name, m in _models().items():
|
| 548 |
if name == "lr":
|
| 549 |
A, B = Xtr.fillna(0), Xte.fillna(0)
|
| 550 |
m.fit(A, ytr, logisticregression__sample_weight=w)
|
|
@@ -598,7 +601,71 @@ def _nested(p, f, sizes, horizon, fee, grid=(0.52, 0.54, 0.56, 0.58, 0.60, 0.62)
|
|
| 598 |
return _stats(np.concatenate(trades) if trades else np.array([]))
|
| 599 |
|
| 600 |
|
| 601 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
"""Purged expanding-window walk-forward. Döner: OOS olasılık, satır indeksi, fold boyutları, ort. train-test AUC farkı."""
|
| 603 |
n = len(X)
|
| 604 |
edges = np.linspace(int(n * 0.4), n, n_folds + 1).astype(int)
|
|
@@ -608,7 +675,7 @@ def _walk(X, Y, F, W, horizon, n_folds, k):
|
|
| 608 |
if tr_end < 80:
|
| 609 |
continue
|
| 610 |
p, ptr = _fit_predict(X.iloc[:tr_end], Y.iloc[:tr_end], X.iloc[te0:te1],
|
| 611 |
-
W[:tr_end], F[:tr_end], k, with_train=True)
|
| 612 |
try:
|
| 613 |
gaps.append(roc_auc_score(Y.iloc[:tr_end], ptr) - roc_auc_score(Y.iloc[te0:te1], p))
|
| 614 |
except ValueError:
|
|
@@ -623,7 +690,7 @@ def _walk(X, Y, F, W, horizon, n_folds, k):
|
|
| 623 |
|
| 624 |
|
| 625 |
def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int = 5, ext=None,
|
| 626 |
-
max_feat: int = 40):
|
| 627 |
feats, atr = make_features(df)
|
| 628 |
n_ext = 0
|
| 629 |
if ext is not None:
|
|
@@ -663,14 +730,20 @@ def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int =
|
|
| 663 |
n_dev = int(n_all * 0.8)
|
| 664 |
Xd, Yd, Fd, Wd = X.iloc[:n_dev], Y.iloc[:n_dev], F[:n_dev], W[:n_dev]
|
| 665 |
|
| 666 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 667 |
yo, fo = Yd.values[oos_idx], Fd[oos_idx]
|
| 668 |
|
| 669 |
# Teşhis (ablation): yalnızca temel (fiyat/hacim) özelliklerle aynı test
|
| 670 |
base_cols = [c for c in cols if not c.startswith(("ts_", "dv_"))]
|
| 671 |
auc_base = None
|
| 672 |
if len(base_cols) < len(cols):
|
| 673 |
-
pb, ib, _, _ = _walk(Xd[base_cols], Yd, Fd, Wd, horizon, n_folds, max_feat)
|
| 674 |
try:
|
| 675 |
auc_base = float(roc_auc_score(Yd.values[ib], pb))
|
| 676 |
except ValueError:
|
|
@@ -701,7 +774,7 @@ def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int =
|
|
| 701 |
ho = None
|
| 702 |
tr_end = n_dev - horizon
|
| 703 |
if tr_end >= 200 and n_all - n_dev >= 100:
|
| 704 |
-
ph = _fit_predict(X.iloc[:tr_end], Y.iloc[:tr_end], X.iloc[n_dev:], W[:tr_end], F[:tr_end], max_feat)
|
| 705 |
try:
|
| 706 |
auc_h = float(roc_auc_score(Y.values[n_dev:], ph))
|
| 707 |
except ValueError:
|
|
@@ -710,7 +783,7 @@ def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int =
|
|
| 710 |
**_stats(_trades(ph, F[n_dev:], horizon, best["thr"], fee))}
|
| 711 |
|
| 712 |
# Son model: tüm veriyle, canlı tahmin
|
| 713 |
-
final_p = _fit_predict(X, Y, feats.iloc[[-1]][cols].ffill().fillna(0), W, F, max_feat)
|
| 714 |
p_up = float(final_p[0])
|
| 715 |
|
| 716 |
price, a = float(close.iloc[-1]), float(atr.iloc[-1])
|
|
@@ -721,7 +794,7 @@ def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int =
|
|
| 721 |
"center": center, "low": center - move, "high": center + move,
|
| 722 |
"thr": best["thr"], "bt": best, "n_oos": len(oos_p), "fee": fee,
|
| 723 |
"n_ext": n_ext, "n_feat": len(cols), "auc_base": auc_base, "max_feat": max_feat,
|
| 724 |
-
"gap": gap, "auc_p": auc_p, "nested": nested, "holdout": ho,
|
| 725 |
}
|
| 726 |
|
| 727 |
|
|
@@ -772,7 +845,7 @@ def _root(e):
|
|
| 772 |
return f"{type(e).__name__}: {e}"
|
| 773 |
|
| 774 |
|
| 775 |
-
def run(symbol, timeframe, exchange, horizon, limit, use_deriv=True, max_feat=40):
|
| 776 |
try:
|
| 777 |
ohlcv, deep, ind, extra = asyncio.run(run_async(symbol, timeframe, exchange, horizon, limit))
|
| 778 |
df = to_df(ohlcv)
|
|
@@ -783,7 +856,8 @@ def run(symbol, timeframe, exchange, horizon, limit, use_deriv=True, max_feat=40
|
|
| 783 |
ext = indicator_features(ind, df)
|
| 784 |
if dfeat is not None:
|
| 785 |
ext = dfeat if ext is None else pd.concat([ext, dfeat], axis=1)
|
| 786 |
-
res = predict(df, int(horizon), ext=ext, max_feat=int(max_feat)
|
|
|
|
| 787 |
except BaseException as e: # noqa: BLE001
|
| 788 |
import traceback
|
| 789 |
traceback.print_exc()
|
|
@@ -799,6 +873,16 @@ def run(symbol, timeframe, exchange, horizon, limit, use_deriv=True, max_feat=40
|
|
| 799 |
("Hold-out AUC > 0.50", ho is not None and ho["auc"] > 0.50),
|
| 800 |
("Hold-out net getiri > 0 (≥20 işlem)", ho is not None and ho["n"] >= 20 and ho["mean"] > 0),
|
| 801 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 802 |
passed = sum(ok for _, ok in checks)
|
| 803 |
edge = f"✅ {passed}/5 kriter" if passed >= 4 else f"⚠️ {passed}/5 kriter — kanıtlanamadı"
|
| 804 |
checks_md = "**Aşırı uyum / güvenilirlik göstergesi**\n\n" + "\n".join(
|
|
@@ -817,6 +901,7 @@ def run(symbol, timeframe, exchange, horizon, limit, use_deriv=True, max_feat=40
|
|
| 817 |
| Ort. net getiri / işlem | {bt['mean']:.3%} (t = {bt['t']:.2f}, ücret {res['fee']:.2%}/işlem) |
|
| 818 |
| Özellik sayısı | {res['n_feat']} (Tickscope/türev: {res['n_ext']}) → fold başına en fazla {res['max_feat']} seçilir |
|
| 819 |
| AUC yalnızca temel özelliklerle | {('%.3f' % res['auc_base']) if res['auc_base'] is not None else '—'} (ek veri kaynakları yardım ediyor mu?) |
|
|
|
|
| 820 |
| Train–test AUC farkı (aşırı uyum) | {res['gap']:.3f} |
|
| 821 |
| AUC anlamlılığı (tek yönlü p) | {res['auc_p']:.3f} |
|
| 822 |
| Nested (dürüst) net getiri / işlem | {nest['mean']:.3%} (t = {nest['t']:.2f}, {nest['n']} işlem) |
|
|
@@ -856,12 +941,16 @@ with gr.Blocks(title="Tickscope Tahmin") as demo:
|
|
| 856 |
limit = gr.Slider(300, 20000, value=5000, step=100, label="Mum sayısı (1000 üstü sayfalanır)")
|
| 857 |
use_deriv = gr.Checkbox(True, label="Türev verisi (LiquidVision MCP: funding/OI) — mumları geçmişin kapsadığı aralığa kırpabilir")
|
| 858 |
max_feat = gr.Slider(10, 150, value=40, step=5, label="Maks. özellik (fold içinde seçilir; az = daha az aşırı uyum)")
|
|
|
|
|
|
|
|
|
|
| 859 |
btn = gr.Button("Tahmin et", variant="primary")
|
| 860 |
out_md = gr.Markdown()
|
| 861 |
out_plot = gr.Plot()
|
| 862 |
with gr.Accordion("Tickscope ham çıktı (deep_analyze / indicators)", open=False):
|
| 863 |
out_raw = gr.Code(language="json")
|
| 864 |
-
btn.click(run, [symbol, timeframe, exchange, horizon, limit, use_deriv, max_feat], [out_md, out_plot, out_raw])
|
| 865 |
|
| 866 |
if __name__ == "__main__":
|
| 867 |
demo.launch()
|
|
|
|
|
|
| 510 |
return f.replace([np.inf, -np.inf], np.nan), atr
|
| 511 |
|
| 512 |
|
| 513 |
+
def _models(hp=None):
|
| 514 |
+
"""hp (Optuna'dan): {"hgb": {...}, "et": {...}, "lr": {"C": ...}}; yoksa varsayılanlar."""
|
| 515 |
+
hp = hp or {}
|
| 516 |
+
h = {"max_depth": 3, "learning_rate": 0.04, "max_iter": 250, "l2_regularization": 2.0,
|
| 517 |
+
"min_samples_leaf": 40, **hp.get("hgb", {})}
|
| 518 |
+
e = {"n_estimators": 300, "max_depth": 6, "min_samples_leaf": 30, "max_features": 0.5, **hp.get("et", {})}
|
| 519 |
+
c = hp.get("lr", {}).get("C", 0.05)
|
| 520 |
return {
|
| 521 |
+
"hgb": HistGradientBoostingClassifier(**h, random_state=42),
|
| 522 |
+
"et": ExtraTreesClassifier(**e, n_jobs=-1, random_state=42),
|
| 523 |
+
"lr": make_pipeline(StandardScaler(), LogisticRegression(C=c, max_iter=500)),
|
|
|
|
|
|
|
|
|
|
| 524 |
}
|
| 525 |
|
| 526 |
|
|
|
|
| 540 |
return keep
|
| 541 |
|
| 542 |
|
| 543 |
+
def _fit_predict(Xtr, ytr, Xte, w=None, ftr=None, k=0, with_train=False, hp=None):
|
| 544 |
"""Ensemble: HGB + ExtraTrees + Logistic -> olasılık ortalaması.
|
| 545 |
k>0: fold-içi özellik seçimi. with_train: eğitim verisi üzerindeki olasılıkları da döndür (aşırı uyum ölçümü için)."""
|
| 546 |
if k and ftr is not None:
|
| 547 |
sel = _select(Xtr, ftr, k)
|
| 548 |
Xtr, Xte = Xtr[sel], Xte[sel]
|
| 549 |
ps, pt = [], []
|
| 550 |
+
for name, m in _models(hp).items():
|
| 551 |
if name == "lr":
|
| 552 |
A, B = Xtr.fillna(0), Xte.fillna(0)
|
| 553 |
m.fit(A, ytr, logisticregression__sample_weight=w)
|
|
|
|
| 601 |
return _stats(np.concatenate(trades) if trades else np.array([]))
|
| 602 |
|
| 603 |
|
| 604 |
+
class _Fixed:
|
| 605 |
+
"""En iyi parametreleri aynı `suggest_*` arayüzüyle geri üretmek için."""
|
| 606 |
+
def __init__(self, params):
|
| 607 |
+
self.p = params
|
| 608 |
+
|
| 609 |
+
def suggest_int(self, name, *a, **k):
|
| 610 |
+
return self.p[name]
|
| 611 |
+
|
| 612 |
+
def suggest_float(self, name, *a, **k):
|
| 613 |
+
return self.p[name]
|
| 614 |
+
|
| 615 |
+
|
| 616 |
+
def _hp_space(t):
|
| 617 |
+
return {
|
| 618 |
+
"hgb": {"max_depth": t.suggest_int("hgb_depth", 2, 5),
|
| 619 |
+
"learning_rate": t.suggest_float("hgb_lr", 0.01, 0.1, log=True),
|
| 620 |
+
"max_iter": t.suggest_int("hgb_iter", 100, 400, step=50),
|
| 621 |
+
"l2_regularization": t.suggest_float("hgb_l2", 0.5, 10.0, log=True),
|
| 622 |
+
"min_samples_leaf": t.suggest_int("hgb_leaf", 20, 200, step=20)},
|
| 623 |
+
"et": {"max_depth": t.suggest_int("et_depth", 3, 10),
|
| 624 |
+
"min_samples_leaf": t.suggest_int("et_leaf", 10, 100, step=10),
|
| 625 |
+
"max_features": t.suggest_float("et_mf", 0.2, 0.8)},
|
| 626 |
+
"lr": {"C": t.suggest_float("lr_C", 0.005, 0.5, log=True)},
|
| 627 |
+
}
|
| 628 |
+
|
| 629 |
+
|
| 630 |
+
def _tune(X, Y, F, W, horizon, n_trials, timeout=240):
|
| 631 |
+
"""Optuna: hiperparametre + özellik sayısı (k) ayarı. YALNIZCA geliştirme verisinin ilk %40'ında
|
| 632 |
+
(iç walk-forward, 3 dilim) yapılır; asıl walk-forward OOS ve hold-out'a hiç dokunmaz.
|
| 633 |
+
Amaç: ortalama AUC − 0.5·std (kararsız/şanslı ayarları cezalandırır)."""
|
| 634 |
+
try:
|
| 635 |
+
import optuna
|
| 636 |
+
except Exception: # noqa: BLE001
|
| 637 |
+
return {"error": "optuna kurulu değil (pip install optuna); varsayılan ayarlar kullanıldı"}
|
| 638 |
+
m = int(len(X) * 0.4)
|
| 639 |
+
if m < 500:
|
| 640 |
+
return {"error": f"Ayar bölgesi çok küçük ({m} bar < 500); Optuna atlandı, varsayılanlar kullanıldı"}
|
| 641 |
+
Xt, Yt, Ft, Wt = X.iloc[:m], Y.iloc[:m], F[:m], W[:m]
|
| 642 |
+
edges = np.linspace(int(m * 0.4), m, 4).astype(int)
|
| 643 |
+
|
| 644 |
+
def obj(trial):
|
| 645 |
+
hp = _hp_space(trial)
|
| 646 |
+
k = trial.suggest_int("k", 10, 80, step=10)
|
| 647 |
+
aucs = []
|
| 648 |
+
for j in range(3):
|
| 649 |
+
tr_end, te0, te1 = edges[j] - horizon, edges[j], edges[j + 1]
|
| 650 |
+
if tr_end < 80:
|
| 651 |
+
continue
|
| 652 |
+
p = _fit_predict(Xt.iloc[:tr_end], Yt.iloc[:tr_end], Xt.iloc[te0:te1],
|
| 653 |
+
Wt[:tr_end], Ft[:tr_end], k, hp=hp)
|
| 654 |
+
try:
|
| 655 |
+
aucs.append(roc_auc_score(Yt.iloc[te0:te1], p))
|
| 656 |
+
except ValueError:
|
| 657 |
+
pass
|
| 658 |
+
return float(np.mean(aucs) - 0.5 * np.std(aucs)) if aucs else 0.5
|
| 659 |
+
|
| 660 |
+
optuna.logging.set_verbosity(optuna.logging.WARNING)
|
| 661 |
+
study = optuna.create_study(direction="maximize", sampler=optuna.samplers.TPESampler(seed=42))
|
| 662 |
+
study.optimize(obj, n_trials=int(n_trials), timeout=timeout)
|
| 663 |
+
bp = study.best_params
|
| 664 |
+
return {"hp": _hp_space(_Fixed(bp)), "k": int(bp["k"]), "score": float(study.best_value),
|
| 665 |
+
"trials": len(study.trials), "region": m}
|
| 666 |
+
|
| 667 |
+
|
| 668 |
+
def _walk(X, Y, F, W, horizon, n_folds, k, hp=None):
|
| 669 |
"""Purged expanding-window walk-forward. Döner: OOS olasılık, satır indeksi, fold boyutları, ort. train-test AUC farkı."""
|
| 670 |
n = len(X)
|
| 671 |
edges = np.linspace(int(n * 0.4), n, n_folds + 1).astype(int)
|
|
|
|
| 675 |
if tr_end < 80:
|
| 676 |
continue
|
| 677 |
p, ptr = _fit_predict(X.iloc[:tr_end], Y.iloc[:tr_end], X.iloc[te0:te1],
|
| 678 |
+
W[:tr_end], F[:tr_end], k, with_train=True, hp=hp)
|
| 679 |
try:
|
| 680 |
gaps.append(roc_auc_score(Y.iloc[:tr_end], ptr) - roc_auc_score(Y.iloc[te0:te1], p))
|
| 681 |
except ValueError:
|
|
|
|
| 690 |
|
| 691 |
|
| 692 |
def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int = 5, ext=None,
|
| 693 |
+
max_feat: int = 40, use_optuna: bool = False, n_trials: int = 25):
|
| 694 |
feats, atr = make_features(df)
|
| 695 |
n_ext = 0
|
| 696 |
if ext is not None:
|
|
|
|
| 730 |
n_dev = int(n_all * 0.8)
|
| 731 |
Xd, Yd, Fd, Wd = X.iloc[:n_dev], Y.iloc[:n_dev], F[:n_dev], W[:n_dev]
|
| 732 |
|
| 733 |
+
hp, tuned = None, None
|
| 734 |
+
if use_optuna:
|
| 735 |
+
tuned = _tune(Xd, Yd, Fd, Wd, horizon, n_trials)
|
| 736 |
+
if "error" not in tuned:
|
| 737 |
+
hp, max_feat = tuned["hp"], tuned["k"]
|
| 738 |
+
|
| 739 |
+
oos_p, oos_idx, sizes, gap = _walk(Xd, Yd, Fd, Wd, horizon, n_folds, max_feat, hp)
|
| 740 |
yo, fo = Yd.values[oos_idx], Fd[oos_idx]
|
| 741 |
|
| 742 |
# Teşhis (ablation): yalnızca temel (fiyat/hacim) özelliklerle aynı test
|
| 743 |
base_cols = [c for c in cols if not c.startswith(("ts_", "dv_"))]
|
| 744 |
auc_base = None
|
| 745 |
if len(base_cols) < len(cols):
|
| 746 |
+
pb, ib, _, _ = _walk(Xd[base_cols], Yd, Fd, Wd, horizon, n_folds, max_feat, hp)
|
| 747 |
try:
|
| 748 |
auc_base = float(roc_auc_score(Yd.values[ib], pb))
|
| 749 |
except ValueError:
|
|
|
|
| 774 |
ho = None
|
| 775 |
tr_end = n_dev - horizon
|
| 776 |
if tr_end >= 200 and n_all - n_dev >= 100:
|
| 777 |
+
ph = _fit_predict(X.iloc[:tr_end], Y.iloc[:tr_end], X.iloc[n_dev:], W[:tr_end], F[:tr_end], max_feat, hp=hp)
|
| 778 |
try:
|
| 779 |
auc_h = float(roc_auc_score(Y.values[n_dev:], ph))
|
| 780 |
except ValueError:
|
|
|
|
| 783 |
**_stats(_trades(ph, F[n_dev:], horizon, best["thr"], fee))}
|
| 784 |
|
| 785 |
# Son model: tüm veriyle, canlı tahmin
|
| 786 |
+
final_p = _fit_predict(X, Y, feats.iloc[[-1]][cols].ffill().fillna(0), W, F, max_feat, hp=hp)
|
| 787 |
p_up = float(final_p[0])
|
| 788 |
|
| 789 |
price, a = float(close.iloc[-1]), float(atr.iloc[-1])
|
|
|
|
| 794 |
"center": center, "low": center - move, "high": center + move,
|
| 795 |
"thr": best["thr"], "bt": best, "n_oos": len(oos_p), "fee": fee,
|
| 796 |
"n_ext": n_ext, "n_feat": len(cols), "auc_base": auc_base, "max_feat": max_feat,
|
| 797 |
+
"gap": gap, "auc_p": auc_p, "nested": nested, "holdout": ho, "tuned": tuned,
|
| 798 |
}
|
| 799 |
|
| 800 |
|
|
|
|
| 845 |
return f"{type(e).__name__}: {e}"
|
| 846 |
|
| 847 |
|
| 848 |
+
def run(symbol, timeframe, exchange, horizon, limit, use_deriv=True, max_feat=40, use_optuna=False, n_trials=25):
|
| 849 |
try:
|
| 850 |
ohlcv, deep, ind, extra = asyncio.run(run_async(symbol, timeframe, exchange, horizon, limit))
|
| 851 |
df = to_df(ohlcv)
|
|
|
|
| 856 |
ext = indicator_features(ind, df)
|
| 857 |
if dfeat is not None:
|
| 858 |
ext = dfeat if ext is None else pd.concat([ext, dfeat], axis=1)
|
| 859 |
+
res = predict(df, int(horizon), ext=ext, max_feat=int(max_feat),
|
| 860 |
+
use_optuna=bool(use_optuna), n_trials=int(n_trials))
|
| 861 |
except BaseException as e: # noqa: BLE001
|
| 862 |
import traceback
|
| 863 |
traceback.print_exc()
|
|
|
|
| 873 |
("Hold-out AUC > 0.50", ho is not None and ho["auc"] > 0.50),
|
| 874 |
("Hold-out net getiri > 0 (≥20 işlem)", ho is not None and ho["n"] >= 20 and ho["mean"] > 0),
|
| 875 |
]
|
| 876 |
+
t = res["tuned"]
|
| 877 |
+
if t is None:
|
| 878 |
+
opt_txt = "kapalı (varsayılan hiperparametreler)"
|
| 879 |
+
elif "error" in t:
|
| 880 |
+
opt_txt = t["error"]
|
| 881 |
+
else:
|
| 882 |
+
g, e = t["hp"]["hgb"], t["hp"]["et"]
|
| 883 |
+
opt_txt = (f"{t['trials']} deneme · iç skor {t['score']:.3f} · k={t['k']} · "
|
| 884 |
+
f"HGB derinlik {g['max_depth']}, lr {g['learning_rate']:.3f} · ET derinlik {e['max_depth']} · "
|
| 885 |
+
f"LR C={t['hp']['lr']['C']:.3f} (yalnızca ilk %40'ta ayarlandı)")
|
| 886 |
passed = sum(ok for _, ok in checks)
|
| 887 |
edge = f"✅ {passed}/5 kriter" if passed >= 4 else f"⚠️ {passed}/5 kriter — kanıtlanamadı"
|
| 888 |
checks_md = "**Aşırı uyum / güvenilirlik göstergesi**\n\n" + "\n".join(
|
|
|
|
| 901 |
| Ort. net getiri / işlem | {bt['mean']:.3%} (t = {bt['t']:.2f}, ücret {res['fee']:.2%}/işlem) |
|
| 902 |
| Özellik sayısı | {res['n_feat']} (Tickscope/türev: {res['n_ext']}) → fold başına en fazla {res['max_feat']} seçilir |
|
| 903 |
| AUC yalnızca temel özelliklerle | {('%.3f' % res['auc_base']) if res['auc_base'] is not None else '—'} (ek veri kaynakları yardım ediyor mu?) |
|
| 904 |
+
| Optuna | {opt_txt} |
|
| 905 |
| Train–test AUC farkı (aşırı uyum) | {res['gap']:.3f} |
|
| 906 |
| AUC anlamlılığı (tek yönlü p) | {res['auc_p']:.3f} |
|
| 907 |
| Nested (dürüst) net getiri / işlem | {nest['mean']:.3%} (t = {nest['t']:.2f}, {nest['n']} işlem) |
|
|
|
|
| 941 |
limit = gr.Slider(300, 20000, value=5000, step=100, label="Mum sayısı (1000 üstü sayfalanır)")
|
| 942 |
use_deriv = gr.Checkbox(True, label="Türev verisi (LiquidVision MCP: funding/OI) — mumları geçmişin kapsadığı aralığa kırpabilir")
|
| 943 |
max_feat = gr.Slider(10, 150, value=40, step=5, label="Maks. özellik (fold içinde seçilir; az = daha az aşırı uyum)")
|
| 944 |
+
with gr.Row():
|
| 945 |
+
use_optuna = gr.Checkbox(False, label="Optuna ile hiperparametre ayarı (OOS/hold-out'a dokunmaz; yavaş)")
|
| 946 |
+
n_trials = gr.Slider(10, 100, value=25, step=5, label="Optuna deneme sayısı")
|
| 947 |
btn = gr.Button("Tahmin et", variant="primary")
|
| 948 |
out_md = gr.Markdown()
|
| 949 |
out_plot = gr.Plot()
|
| 950 |
with gr.Accordion("Tickscope ham çıktı (deep_analyze / indicators)", open=False):
|
| 951 |
out_raw = gr.Code(language="json")
|
| 952 |
+
btn.click(run, [symbol, timeframe, exchange, horizon, limit, use_deriv, max_feat, use_optuna, n_trials], [out_md, out_plot, out_raw])
|
| 953 |
|
| 954 |
if __name__ == "__main__":
|
| 955 |
demo.launch()
|
| 956 |
+
|