GoshawkVortexAI commited on
Commit
901006e
·
verified ·
1 Parent(s): 7523d98

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -8
app.py CHANGED
@@ -33,7 +33,7 @@ COMBO_MODES = ["Kapalı", "Onay filtresi (KNN + birleşik)", "Sadece birleşik s
33
  LDC_MODES = ["Kapalı", "Onay filtresi (Lorentzian)", "Sadece Lorentzian"]
34
  VP_MODES = ["Kapalı", "Onay filtresi (POC / Value Area)", "KNN özelliği + onay filtresi"]
35
  GANN_MODES = ["Kapalı", "Onay filtresi (Gann Box %50)"]
36
- SMC_MODES = ["Kapalı", "Onay filtresi (SMC yapı yönü)"]
37
  SMC_SRC = ["Swing yapı", "Internal yapı"]
38
  GANN_LEVELS = [0.0, 0.236, 0.382, 0.5, 0.618, 0.786, 1.0]
39
  GANN_FAN = [(8, "8x1"), (4, "4x1"), (3, "3x1"), (2, "2x1"), (1, "1x1"),
@@ -194,6 +194,7 @@ def smc_analyze(df, swing_len=50, int_len=5, eq_len=3, eq_thr=0.1, ob_keep=5):
194
  s_tr = np.zeros(n, dtype=int)
195
  i_tr = np.zeros(n, dtype=int)
196
  top_a, bot_a = np.full(n, np.nan), np.full(n, np.nan)
 
197
  st = it = 0
198
  top, bot = h[0], l[0]
199
  events, obs, points, eqs, fvgs = [], [], [], [], []
@@ -267,6 +268,7 @@ def smc_analyze(df, swing_len=50, int_len=5, eq_len=3, eq_thr=0.1, ob_keep=5):
267
  s_tr[i], i_tr[i] = st, it
268
  top, bot = max(top, h[i]), min(bot, l[i])
269
  top_a[i], bot_a[i] = top, bot
 
270
  # --- Fair Value Gap
271
  if i >= 2:
272
  delta = (c[i-1]-o[i-1])/(o[i-1]*100) if o[i-1] else 0.0
@@ -281,7 +283,7 @@ def smc_analyze(df, swing_len=50, int_len=5, eq_len=3, eq_thr=0.1, ob_keep=5):
281
  fvgs.append({"bull": False, "top": float(l[i-2]), "bot": float(h[i]), "idx": i-1, "on": True})
282
  live = lambda internal, bull: [o_ for o_ in obs if o_["on"] and o_["internal"] == internal
283
  and o_["bull"] == bull][-int(ob_keep):]
284
- return {"swing_trend": s_tr, "internal_trend": i_tr, "top": top_a, "bot": bot_a,
285
  "events": events, "points": points, "eq": eqs,
286
  "obs": live(True, True)+live(True, False)+live(False, True)+live(False, False),
287
  "fvg": [g for g in fvgs if g["on"]][-8:], "strong_high": st == -1, "strong_low": st == 1}
@@ -1011,6 +1013,7 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1011
  gann_now = int(gann_arr[-1])
1012
  GB = gann_box(df, int(gann_lb), bool(gann_rev))
1013
  smc_on = smc_mode != SMC_MODES[0]
 
1014
  SM = smc_analyze(df, int(smc_swing_len), int(smc_int_len)) if (smc_on or smc_draw) else None
1015
  smc_arr = np.zeros(len(df), dtype=int)
1016
  if SM is not None:
@@ -1020,6 +1023,14 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1020
  zone_ = np.where(df.Close.to_numpy(float) < mid_, 1, np.where(df.Close.to_numpy(float) > mid_, -1, 0))
1021
  smc_arr = np.where(zone_ == smc_arr, smc_arr, 0).astype(int)
1022
  smc_now = int(smc_arr[-1])
 
 
 
 
 
 
 
 
1023
 
1024
  valid = X_all.notna().all(axis=1) & y_all.notna()
1025
  X = X_all.loc[valid].copy()
@@ -1059,6 +1070,9 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1059
  if combo_only: # oylar zaten birleşik sinyale girer; tekil filtreler çift sayılmasın
1060
  ind_only = ind_confirm = vp_on = False
1061
  ind_only = ind_only and not ldc_only # iki "Sadece" modu birlikteyse Lorentzian öncelikli
 
 
 
1062
  need_ldc = ldc_mode != LDC_MODES[0] or combo_on
1063
  LD = ldc_classify(df, ldc_k, ldc_back, ldc_regime, ldc_kern_lb, ldc_kern_rw,
1064
  use_vol=bool(ldc_use_vol), use_regime=bool(ldc_use_regime),
@@ -1091,8 +1105,10 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1091
  smin, smax = float(tpsl_smin), float(tpsl_smax)
1092
  sd_of = lambda d: np.clip(np.where(np.isfinite(d), d+0.1*a_, 1.5*a_), smin*a_, smax*a_)
1093
  cap_of = lambda d: np.where(d >= 1.0*a_, d, np.inf)
1094
- A["ind_sd"] = {1: sd_of(nearest([st_line, ut_stop, vpl], 1)),
1095
- -1: sd_of(nearest([st_line, ut_stop, vph], -1))}
 
 
1096
  A["ind_cap"] = {1: cap_of(nearest([vpo, vph], -1)),
1097
  -1: cap_of(nearest([vpo, vpl], 1))}
1098
 
@@ -1123,6 +1139,8 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1123
  side = ldc_now
1124
  if combo_only and combo_now != 0 and allow[combo_now]:
1125
  side = combo_now
 
 
1126
  p_side, p_opp = (p_up, p_down) if side == 1 else (p_down, p_up)
1127
 
1128
  imp, scaler = cal_model.named_steps["imputer"], cal_model.named_steps["scale"]
@@ -1135,6 +1153,8 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1135
  agreement = float((ldc_arr[-10:] == side).mean())
1136
  if combo_only:
1137
  agreement = float((combo_arr[-10:] == side).mean())
 
 
1138
 
1139
  # --- yön bazlı TP/SL optimizasyonu (yalnızca geliştirme verisi)
1140
  current_regime = str(regimes_all.iloc[-1])
@@ -1153,8 +1173,10 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1153
  f_ = [i for i in f_ if vp_arr[i] == s_]
1154
  if gann_on:
1155
  f_ = [i for i in f_ if gann_arr[i] == s_]
1156
- if smc_on:
1157
  f_ = [i for i in f_ if smc_arr[i] == s_]
 
 
1158
  return f_ if len(f_) >= 35 else dev_pos
1159
  for s in (1, -1):
1160
  if allow[s]:
@@ -1185,6 +1207,11 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1185
  oos_bacc = float(balanced_accuracy_score(oos_y, oos_pred))
1186
  oos_acc = float(accuracy_score(oos_y, oos_pred))
1187
 
 
 
 
 
 
1188
  rows, busy = [], -1
1189
  for i, pred in zip(oos_pos_arr, oos_pred):
1190
  pred = int(pred)
@@ -1235,6 +1262,8 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1235
  cands = {"Supertrend": float(st_line[-1]), "UT trailing stop": float(ut_stop[-1]),
1236
  "VP " + ("VAL" if side == 1 else "VAH"):
1237
  float((vp.val if side == 1 else vp.vah).iloc[-1])}
 
 
1238
  valid = {k_: side*(cl_-v_) for k_, v_ in cands.items() if np.isfinite(v_) and side*(cl_-v_) > 0}
1239
  sl_name = min(valid, key=valid.get) if valid else "ATR varsayılan (seviye yok)"
1240
  else:
@@ -1268,8 +1297,10 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1268
  ]
1269
  dname = {1: "LONG ↑", -1: "SHORT ↓", 0: "belirsiz"}
1270
  ind_check = ("İndikatör yönü (ST + UT aynı)", dname[ind_now], "yönle aynı", ind_now == side)
1271
- if ind_only or ldc_only or combo_only:
1272
  keep = ("Yön izni", "OOS balanced acc.", "OOS işlem sayısı", "OOS expectancy")
 
 
1273
  checks = [c for c in checks if c[0] in keep]
1274
  if ind_only or ind_confirm:
1275
  checks.insert(1, ind_check)
@@ -1401,7 +1432,7 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1401
  ("Volume Profile (POC/VA)", dname[vp_now]),
1402
  ("**Birleşik sinyal**", f"**{dname[combo_now]}** (en az {mv} oy, karşı oy yok)")])
1403
  else:
1404
- combo_md = "_Mod kapalı._"
1405
  if ind_tpsl:
1406
  capped = target_d < stop_d*rr-1e-12
1407
  tp_title = "indikatörlerden türetildi"
@@ -1528,7 +1559,7 @@ def run_engine(ticker, period, horizon, side_mode, equity, min_risk, max_risk,
1528
  "seri korelasyonunu ve rejim değişimini tam modellemez. Pozisyon hesabı spot miktar "
1529
  "varsayar; CFD lot sözleşmesi, spread, funding, swap, komisyon, minimum lot, marjin ve "
1530
  "broker fiyatı farklı olabilir. Gap ve kayma kaybı planlanan riskin üstüne çıkarabilir. "
1531
- "Supertrend ve UT Bot, TradingView formüllerinin Python portudur; ATR başlangıcı ve veri kaynağı yüzünden TV değerlerinden küçük sapmalar olabilir. Birleşik sinyal; ST+UT, Lorentzian ve Volume Profile oylarının birleşimidir. İndikatör bazlı TP/SL, en yakın ST/UT/VP seviyesini invalidasyon sayar ve ATR aralığına sıkıştırır. Lorentzian Classification, jdehorty'nin TradingView göstergesinin Python portudur (ANN komşu seçimi, filtreler ve kernel regresyon); Pine kaynağıyla birebir aynı sonuç vermeyebilir ve yalnızca günlük mumda çalışır. Volume Profile, günlük OHLCV'den (her mumun hacmi high–low aralığına eşit dağıtılarak) yaklaşık hesaplanır; TradingView VPVR'nin alt-zaman dilimi verisiyle birebir aynı olmaz. Gann Box, Zeiierman göstergesinin açıklamasına göre yazılmış bir Python portudur (Pine kaynağı birebir alınmadı); kutu son N mumun en yüksek/en düşük noktasından kurulur, Gann Fan 1x1 köşegeni ve katlarıyla çizilir, Gann Curves/Angles eklenmedi. Onay filtresi, kapanışın kutu %50 çizgisine göre konumuna bakar ve geçmişe bakan (kayan) pencere kullanır. SMC, LuxAlgo göstergesinin açıklamasına göre yazılmış bir Python portudur (Pine kaynağı birebir değil): swing/internal yapı, BOS/CHoCH, order block (high/low mitigasyonu), EQH/EQL, FVG ve premium/discount hesaplanır; MTF önceki high/low ve mum boyama yoktur. Pivotlar pencere kadar mum sonra doğrulanır, bu yüzden sinyal geç gelir. SMC kavramlarının istatistiksel geçerliliği kanıtlı değildir; OOS sonuçlarıyla doğrulayın. Canlı hesap öncesi paper trading ve broker bazlı doğrulama zorunludur."
1532
  )
1533
  return (report, prob_figure(p_down, p_flat, p_up), price_fig, eq_fig, pf_fig, mc_fig,
1534
  top_df, csv_path, disclaimer)
 
33
  LDC_MODES = ["Kapalı", "Onay filtresi (Lorentzian)", "Sadece Lorentzian"]
34
  VP_MODES = ["Kapalı", "Onay filtresi (POC / Value Area)", "KNN özelliği + onay filtresi"]
35
  GANN_MODES = ["Kapalı", "Onay filtresi (Gann Box %50)"]
36
+ SMC_MODES = ["Kapalı", "Onay filtresi (SMC yapı yönü)", "Sadece SMC (yapı kırılımı girişi)"]
37
  SMC_SRC = ["Swing yapı", "Internal yapı"]
38
  GANN_LEVELS = [0.0, 0.236, 0.382, 0.5, 0.618, 0.786, 1.0]
39
  GANN_FAN = [(8, "8x1"), (4, "4x1"), (3, "3x1"), (2, "2x1"), (1, "1x1"),
 
194
  s_tr = np.zeros(n, dtype=int)
195
  i_tr = np.zeros(n, dtype=int)
196
  top_a, bot_a = np.full(n, np.nan), np.full(n, np.nan)
197
+ swh_a, swl_a = np.full(n, np.nan), np.full(n, np.nan)
198
  st = it = 0
199
  top, bot = h[0], l[0]
200
  events, obs, points, eqs, fvgs = [], [], [], [], []
 
268
  s_tr[i], i_tr[i] = st, it
269
  top, bot = max(top, h[i]), min(bot, l[i])
270
  top_a[i], bot_a[i] = top, bot
271
+ swh_a[i], swl_a[i] = sh["lvl"], sl_["lvl"]
272
  # --- Fair Value Gap
273
  if i >= 2:
274
  delta = (c[i-1]-o[i-1])/(o[i-1]*100) if o[i-1] else 0.0
 
283
  fvgs.append({"bull": False, "top": float(l[i-2]), "bot": float(h[i]), "idx": i-1, "on": True})
284
  live = lambda internal, bull: [o_ for o_ in obs if o_["on"] and o_["internal"] == internal
285
  and o_["bull"] == bull][-int(ob_keep):]
286
+ return {"swing_trend": s_tr, "internal_trend": i_tr, "top": top_a, "bot": bot_a, "sw_hi": swh_a, "sw_lo": swl_a,
287
  "events": events, "points": points, "eq": eqs,
288
  "obs": live(True, True)+live(True, False)+live(False, True)+live(False, False),
289
  "fvg": [g for g in fvgs if g["on"]][-8:], "strong_high": st == -1, "strong_low": st == 1}
 
1013
  gann_now = int(gann_arr[-1])
1014
  GB = gann_box(df, int(gann_lb), bool(gann_rev))
1015
  smc_on = smc_mode != SMC_MODES[0]
1016
+ smc_only = smc_mode == SMC_MODES[2]
1017
  SM = smc_analyze(df, int(smc_swing_len), int(smc_int_len)) if (smc_on or smc_draw) else None
1018
  smc_arr = np.zeros(len(df), dtype=int)
1019
  if SM is not None:
 
1023
  zone_ = np.where(df.Close.to_numpy(float) < mid_, 1, np.where(df.Close.to_numpy(float) > mid_, -1, 0))
1024
  smc_arr = np.where(zone_ == smc_arr, smc_arr, 0).astype(int)
1025
  smc_now = int(smc_arr[-1])
1026
+ smc_entry = np.zeros(len(df), dtype=int) # yalnızca yapı kırılımı mumlarında giriş
1027
+ if SM is not None:
1028
+ want_internal = smc_src == SMC_SRC[1]
1029
+ ev_arr = np.zeros(len(df), dtype=int)
1030
+ for e_ in SM["events"]:
1031
+ if e_["internal"] == want_internal:
1032
+ ev_arr[e_["i"]] = 1 if e_["bull"] else -1
1033
+ smc_entry = np.where(ev_arr == smc_arr, ev_arr, 0).astype(int)
1034
 
1035
  valid = X_all.notna().all(axis=1) & y_all.notna()
1036
  X = X_all.loc[valid].copy()
 
1070
  if combo_only: # oylar zaten birleşik sinyale girer; tekil filtreler çift sayılmasın
1071
  ind_only = ind_confirm = vp_on = False
1072
  ind_only = ind_only and not ldc_only # iki "Sadece" modu birlikteyse Lorentzian öncelikli
1073
+ if smc_only: # backtest yalnızca SMC girişlerine göre; diğer sinyal/filtre modları devre dışı
1074
+ ind_only = ind_confirm = vp_on = ldc_on = ldc_only = ldc_confirm = False
1075
+ combo_on = combo_only = False
1076
  need_ldc = ldc_mode != LDC_MODES[0] or combo_on
1077
  LD = ldc_classify(df, ldc_k, ldc_back, ldc_regime, ldc_kern_lb, ldc_kern_rw,
1078
  use_vol=bool(ldc_use_vol), use_regime=bool(ldc_use_regime),
 
1105
  smin, smax = float(tpsl_smin), float(tpsl_smax)
1106
  sd_of = lambda d: np.clip(np.where(np.isfinite(d), d+0.1*a_, 1.5*a_), smin*a_, smax*a_)
1107
  cap_of = lambda d: np.where(d >= 1.0*a_, d, np.inf)
1108
+ lv_l = [st_line, ut_stop, vpl] + ([SM["sw_lo"]] if (smc_only and SM is not None) else [])
1109
+ lv_s = [st_line, ut_stop, vph] + ([SM["sw_hi"]] if (smc_only and SM is not None) else [])
1110
+ A["ind_sd"] = {1: sd_of(nearest(lv_l, 1)),
1111
+ -1: sd_of(nearest(lv_s, -1))}
1112
  A["ind_cap"] = {1: cap_of(nearest([vpo, vph], -1)),
1113
  -1: cap_of(nearest([vpo, vpl], 1))}
1114
 
 
1139
  side = ldc_now
1140
  if combo_only and combo_now != 0 and allow[combo_now]:
1141
  side = combo_now
1142
+ if smc_only and smc_now != 0 and allow[smc_now]:
1143
+ side = smc_now
1144
  p_side, p_opp = (p_up, p_down) if side == 1 else (p_down, p_up)
1145
 
1146
  imp, scaler = cal_model.named_steps["imputer"], cal_model.named_steps["scale"]
 
1153
  agreement = float((ldc_arr[-10:] == side).mean())
1154
  if combo_only:
1155
  agreement = float((combo_arr[-10:] == side).mean())
1156
+ if smc_only:
1157
+ agreement = float((smc_arr[-10:] == side).mean())
1158
 
1159
  # --- yön bazlı TP/SL optimizasyonu (yalnızca geliştirme verisi)
1160
  current_regime = str(regimes_all.iloc[-1])
 
1173
  f_ = [i for i in f_ if vp_arr[i] == s_]
1174
  if gann_on:
1175
  f_ = [i for i in f_ if gann_arr[i] == s_]
1176
+ if smc_on and not smc_only:
1177
  f_ = [i for i in f_ if smc_arr[i] == s_]
1178
+ if smc_only:
1179
+ f_ = [i for i in f_ if smc_entry[i] == s_]
1180
  return f_ if len(f_) >= 35 else dev_pos
1181
  for s in (1, -1):
1182
  if allow[s]:
 
1207
  oos_bacc = float(balanced_accuracy_score(oos_y, oos_pred))
1208
  oos_acc = float(accuracy_score(oos_y, oos_pred))
1209
 
1210
+ if smc_only: # metrik: SMC yön durumu; işlem: yapı kırılımı mumları
1211
+ oos_pred = smc_arr[oos_pos_arr]
1212
+ oos_bacc = float(balanced_accuracy_score(oos_y, oos_pred))
1213
+ oos_acc = float(accuracy_score(oos_y, oos_pred))
1214
+ oos_pred = smc_entry[oos_pos_arr]
1215
  rows, busy = [], -1
1216
  for i, pred in zip(oos_pos_arr, oos_pred):
1217
  pred = int(pred)
 
1262
  cands = {"Supertrend": float(st_line[-1]), "UT trailing stop": float(ut_stop[-1]),
1263
  "VP " + ("VAL" if side == 1 else "VAH"):
1264
  float((vp.val if side == 1 else vp.vah).iloc[-1])}
1265
+ if smc_only and SM is not None:
1266
+ cands["SMC swing " + ("low" if side == 1 else "high")] = float(SM["sw_lo" if side == 1 else "sw_hi"][-1])
1267
  valid = {k_: side*(cl_-v_) for k_, v_ in cands.items() if np.isfinite(v_) and side*(cl_-v_) > 0}
1268
  sl_name = min(valid, key=valid.get) if valid else "ATR varsayılan (seviye yok)"
1269
  else:
 
1297
  ]
1298
  dname = {1: "LONG ↑", -1: "SHORT ↓", 0: "belirsiz"}
1299
  ind_check = ("İndikatör yönü (ST + UT aynı)", dname[ind_now], "yönle aynı", ind_now == side)
1300
+ if ind_only or ldc_only or combo_only or smc_only:
1301
  keep = ("Yön izni", "OOS balanced acc.", "OOS işlem sayısı", "OOS expectancy")
1302
+ if smc_only:
1303
+ keep = tuple(k_ for k_ in keep if k_ != "OOS balanced acc.")
1304
  checks = [c for c in checks if c[0] in keep]
1305
  if ind_only or ind_confirm:
1306
  checks.insert(1, ind_check)
 
1432
  ("Volume Profile (POC/VA)", dname[vp_now]),
1433
  ("**Birleşik sinyal**", f"**{dname[combo_now]}** (en az {mv} oy, karşı oy yok)")])
1434
  else:
1435
+ combo_md = "_SMC-only modunda devre dışı._" if smc_only else "_Mod kapalı._"
1436
  if ind_tpsl:
1437
  capped = target_d < stop_d*rr-1e-12
1438
  tp_title = "indikatörlerden türetildi"
 
1559
  "seri korelasyonunu ve rejim değişimini tam modellemez. Pozisyon hesabı spot miktar "
1560
  "varsayar; CFD lot sözleşmesi, spread, funding, swap, komisyon, minimum lot, marjin ve "
1561
  "broker fiyatı farklı olabilir. Gap ve kayma kaybı planlanan riskin üstüne çıkarabilir. "
1562
+ "Supertrend ve UT Bot, TradingView formüllerinin Python portudur; ATR başlangıcı ve veri kaynağı yüzünden TV değerlerinden küçük sapmalar olabilir. Birleşik sinyal; ST+UT, Lorentzian ve Volume Profile oylarının birleşimidir. İndikatör bazlı TP/SL, en yakın ST/UT/VP seviyesini invalidasyon sayar ve ATR aralığına sıkıştırır. Lorentzian Classification, jdehorty'nin TradingView göstergesinin Python portudur (ANN komşu seçimi, filtreler ve kernel regresyon); Pine kaynağıyla birebir aynı sonuç vermeyebilir ve yalnızca günlük mumda çalışır. Volume Profile, günlük OHLCV'den (her mumun hacmi high–low aralığına eşit dağıtılarak) yaklaşık hesaplanır; TradingView VPVR'nin alt-zaman dilimi verisiyle birebir aynı olmaz. Gann Box, Zeiierman göstergesinin açıklamasına göre yazılmış bir Python portudur (Pine kaynağı birebir alınmadı); kutu son N mumun en yüksek/en düşük noktasından kurulur, Gann Fan 1x1 köşegeni ve katlarıyla çizilir, Gann Curves/Angles eklenmedi. Onay filtresi, kapanışın kutu %50 çizgisine göre konumuna bakar ve geçmişe bakan (kayan) pencere kullanır. SMC, LuxAlgo göstergesinin açıklamasına göre yazılmış bir Python portudur (Pine kaynağı birebir değil): swing/internal yapı, BOS/CHoCH, order block (high/low mitigasyonu), EQH/EQL, FVG ve premium/discount hesaplanır; MTF önceki high/low ve mum boyama yoktur. Sadece SMC modunda işlemler yalnızca seçilen yapıdaki (swing/internal) BOS/CHoCH kırılım mumunda, kırılım yönünde açılır; SL en yakın ST/UT/VP/SMC swing seviyesinden, TP R katından türetilir; diğer sinyal modları devre dışıdır. Pivotlar pencere kadar mum sonra doğrulanır, bu yüzden sinyal geç gelir. SMC kavramlarının istatistiksel geçerliliği kanıtlı değildir; OOS sonuçlarıyla doğrulayın. Canlı hesap öncesi paper trading ve broker bazlı doğrulama zorunludur."
1563
  )
1564
  return (report, prob_figure(p_down, p_flat, p_up), price_fig, eq_fig, pf_fig, mc_fig,
1565
  top_df, csv_path, disclaimer)