GoshawkVortexAI commited on
Commit
9c19d74
·
verified ·
1 Parent(s): a5411a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -4
app.py CHANGED
@@ -66,6 +66,7 @@ ALIASES = {
66
  "exchange": ["exchange"],
67
  "limit": ["limit", "count", "n", "bars"],
68
  "until": ["until", "end", "end_time", "endTime", "to", "before"],
 
69
  }
70
 
71
  EXTRA_TOOLS = ["detect_divergence", "detect_patterns", "analyze_structure",
@@ -146,6 +147,69 @@ async def fetch_ohlcv(session, tools, symbol, timeframe, exchange, total):
146
  return out.to_dict("records")
147
 
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  def to_df(payload) -> pd.DataFrame:
150
  rows = payload
151
  if isinstance(payload, dict):
@@ -304,8 +368,16 @@ def _backtest(p, fwd, horizon, thr, fee):
304
  "hit": float((tr > 0).mean()), "pf": float(gp / gl) if gl > 0 else np.inf}
305
 
306
 
307
- def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int = 5):
308
  feats, atr = make_features(df)
 
 
 
 
 
 
 
 
309
  close = df["close"]
310
  fwd = close.shift(-horizon) / close - 1
311
  y = (fwd > 0).astype(float)
@@ -374,6 +446,7 @@ def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int =
374
  "p_up": p_up, "acc": acc, "baseline": base, "auc": auc, "price": price, "atr": a,
375
  "center": center, "low": center - move, "high": center + move,
376
  "thr": best["thr"], "bt": best, "n_oos": len(oos_p), "fee": fee,
 
377
  }
378
 
379
 
@@ -394,7 +467,8 @@ async def run_async(symbol, timeframe, exchange, horizon, limit):
394
  deep = await call_tool(session, tools, "deep_analyze", symbol=symbol,
395
  timeframe=timeframe, exchange=exchange)
396
  ind = await call_tool(session, tools, "compute_indicators", symbol=symbol,
397
- timeframe=timeframe, exchange=exchange)
 
398
 
399
  # Tickscope'un diğer tüm analiz/piyasa araçları (canlı bağlam; şema uyuşmazsa hata olarak kaydedilir)
400
  extra = {}
@@ -421,7 +495,8 @@ def run(symbol, timeframe, exchange, horizon, limit):
421
  try:
422
  ohlcv, deep, ind, extra = asyncio.run(run_async(symbol, timeframe, exchange, horizon, limit))
423
  df = to_df(ohlcv)
424
- res = predict(df, int(horizon))
 
425
  except BaseException as e: # noqa: BLE001
426
  import traceback
427
  traceback.print_exc()
@@ -441,6 +516,7 @@ def run(symbol, timeframe, exchange, horizon, limit):
441
  | OOS AUC / doğruluk | {res['auc']:.3f} / {res['acc']:.1%} (baseline {res['baseline']:.1%}) |
442
  | OOS işlem sayısı | {bt['n']} (hit {bt['hit']:.1%}, PF {bt['pf']:.2f}) |
443
  | Ort. net getiri / işlem | {bt['mean']:.3%} (t = {bt['t']:.2f}, ücret {res['fee']:.2%}/işlem) |
 
444
  | Model edge | {edge} |
445
 
446
  *Walk-forward (purged) out-of-sample sonuçlar. Eşik OOS'ta seçildiği için hafif iyimser olabilir. Eğitim/araştırma amaçlıdır; yatırım tavsiyesi değildir.*"""
@@ -458,7 +534,7 @@ def run(symbol, timeframe, exchange, horizon, limit):
458
  arrayminus=[res["center"] - res["low"]])))
459
  fig.update_layout(height=450, xaxis_rangeslider_visible=False, margin=dict(l=10, r=10, t=30, b=10))
460
 
461
- raw = json.dumps({"deep_analyze": deep, "compute_indicators": ind, **extra},
462
  indent=2, ensure_ascii=False, default=str)
463
  return md, fig, raw
464
 
 
66
  "exchange": ["exchange"],
67
  "limit": ["limit", "count", "n", "bars"],
68
  "until": ["until", "end", "end_time", "endTime", "to", "before"],
69
+ "include_series": ["include_series", "includeSeries", "series", "with_series"],
70
  }
71
 
72
  EXTRA_TOOLS = ["detect_divergence", "detect_patterns", "analyze_structure",
 
147
  return out.to_dict("records")
148
 
149
 
150
+ def _numeric_list(o, min_len):
151
+ return (isinstance(o, list) and len(o) >= min_len and
152
+ all(x is None or (isinstance(x, (int, float)) and not isinstance(x, bool)) for x in o[:50]))
153
+
154
+
155
+ def extract_series(payload, n):
156
+ """compute_indicators çıktısında gezinip bar bazlı sayısal serileri bulur (şemadan bağımsız)."""
157
+ min_len = max(50, int(n * 0.5))
158
+ out = {}
159
+
160
+ def walk(o, path):
161
+ if isinstance(o, list):
162
+ if _numeric_list(o, min_len):
163
+ out[path] = o
164
+ elif len(o) >= min_len and all(isinstance(x, dict) for x in o[:3]):
165
+ for key in o[0]:
166
+ vals = [r.get(key) if isinstance(r, dict) else None for r in o]
167
+ if _numeric_list(vals, min_len) and key.lower() not in ("ts", "time", "timestamp", "t"):
168
+ out[f"{path}.{key}"] = vals
169
+ elif isinstance(o, dict):
170
+ for k, v in o.items():
171
+ walk(v, f"{path}.{k}" if path else str(k))
172
+
173
+ walk(payload, "")
174
+ return out
175
+
176
+
177
+ def indicator_features(ind, df: pd.DataFrame):
178
+ """Tickscope'un 73 göstergesinin zaman serilerini (varsa) df'e hizalı özellik tablosuna çevirir.
179
+ Fiyat seviyesi gibi duran (SMA/EMA/bant vb.) seriler kapanışa göre normalize edilir."""
180
+ if not isinstance(ind, dict) or "error" in ind:
181
+ return None
182
+ n = len(df)
183
+ close = df["close"].values
184
+ cols = {}
185
+ for path, vals in extract_series(ind, n).items():
186
+ s = pd.to_numeric(pd.Series(vals), errors="coerce").values.astype(float)
187
+ arr = np.full(n, np.nan)
188
+ m = min(len(s), n)
189
+ arr[-m:] = s[-m:] # seriler sondan hizalanır
190
+ if np.isnan(arr).all() or np.nanstd(arr) == 0:
191
+ continue
192
+ ref = np.nanmedian(close[-m:])
193
+ if ref and abs(np.nanmedian(arr) / ref - 1) < 0.5: # fiyat seviyesi -> göreli mesafe
194
+ arr = arr / close - 1
195
+ name = "ts_" + "".join(ch if ch.isalnum() else "_" for ch in path).strip("_")
196
+ cols[name] = arr
197
+ if not cols:
198
+ return None
199
+ return pd.DataFrame(cols, index=df.index)
200
+
201
+
202
+ def _strip_series(o, keep=3):
203
+ """Ham çıktıyı okunur tutmak için uzun serileri son `keep` değere kısaltır."""
204
+ if isinstance(o, list) and len(o) > 20:
205
+ return [f"... {len(o)} değer, son {keep}:"] + o[-keep:]
206
+ if isinstance(o, list):
207
+ return [_strip_series(x, keep) for x in o]
208
+ if isinstance(o, dict):
209
+ return {k: _strip_series(v, keep) for k, v in o.items()}
210
+ return o
211
+
212
+
213
  def to_df(payload) -> pd.DataFrame:
214
  rows = payload
215
  if isinstance(payload, dict):
 
368
  "hit": float((tr > 0).mean()), "pf": float(gp / gl) if gl > 0 else np.inf}
369
 
370
 
371
+ def predict(df: pd.DataFrame, horizon: int, fee: float = 0.0006, n_folds: int = 5, ext=None):
372
  feats, atr = make_features(df)
373
+ n_ext = 0
374
+ if ext is not None:
375
+ ext = ext.replace([np.inf, -np.inf], np.nan)
376
+ w0 = min(60, len(df) // 5)
377
+ # ısınma sonrası %10'dan fazla boş olan Tickscope kolonlarını at
378
+ ext = ext.loc[:, ext.iloc[w0:].isna().mean() <= 0.10]
379
+ n_ext = ext.shape[1]
380
+ feats = pd.concat([feats, ext], axis=1)
381
  close = df["close"]
382
  fwd = close.shift(-horizon) / close - 1
383
  y = (fwd > 0).astype(float)
 
446
  "p_up": p_up, "acc": acc, "baseline": base, "auc": auc, "price": price, "atr": a,
447
  "center": center, "low": center - move, "high": center + move,
448
  "thr": best["thr"], "bt": best, "n_oos": len(oos_p), "fee": fee,
449
+ "n_ext": n_ext, "n_feat": len(cols),
450
  }
451
 
452
 
 
467
  deep = await call_tool(session, tools, "deep_analyze", symbol=symbol,
468
  timeframe=timeframe, exchange=exchange)
469
  ind = await call_tool(session, tools, "compute_indicators", symbol=symbol,
470
+ timeframe=timeframe, exchange=exchange,
471
+ limit=int(limit), include_series=True)
472
 
473
  # Tickscope'un diğer tüm analiz/piyasa araçları (canlı bağlam; şema uyuşmazsa hata olarak kaydedilir)
474
  extra = {}
 
495
  try:
496
  ohlcv, deep, ind, extra = asyncio.run(run_async(symbol, timeframe, exchange, horizon, limit))
497
  df = to_df(ohlcv)
498
+ ext = indicator_features(ind, df)
499
+ res = predict(df, int(horizon), ext=ext)
500
  except BaseException as e: # noqa: BLE001
501
  import traceback
502
  traceback.print_exc()
 
516
  | OOS AUC / doğruluk | {res['auc']:.3f} / {res['acc']:.1%} (baseline {res['baseline']:.1%}) |
517
  | OOS işlem sayısı | {bt['n']} (hit {bt['hit']:.1%}, PF {bt['pf']:.2f}) |
518
  | Ort. net getiri / işlem | {bt['mean']:.3%} (t = {bt['t']:.2f}, ücret {res['fee']:.2%}/işlem) |
519
+ | Özellik sayısı | {res['n_feat']} (Tickscope göstergesi: {res['n_ext']}) |
520
  | Model edge | {edge} |
521
 
522
  *Walk-forward (purged) out-of-sample sonuçlar. Eşik OOS'ta seçildiği için hafif iyimser olabilir. Eğitim/araştırma amaçlıdır; yatırım tavsiyesi değildir.*"""
 
534
  arrayminus=[res["center"] - res["low"]])))
535
  fig.update_layout(height=450, xaxis_rangeslider_visible=False, margin=dict(l=10, r=10, t=30, b=10))
536
 
537
+ raw = json.dumps(_strip_series({"deep_analyze": deep, "compute_indicators": ind, **extra}),
538
  indent=2, ensure_ascii=False, default=str)
539
  return md, fig, raw
540