GoshawkVortexAI commited on
Commit
ea3f43e
·
verified ·
1 Parent(s): 828800b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -95
app.py CHANGED
@@ -1,5 +1,5 @@
1
  import os
2
- import io
3
  import requests
4
  import numpy as np
5
  import pandas as pd
@@ -18,7 +18,71 @@ if api_key:
18
  client = Groq(api_key=api_key)
19
 
20
  # ==========================================
21
- # 📊 2. YARDIMCI FONKSİYONLAR
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  # ==========================================
23
  def compute_rsi(series, period=14):
24
  delta = series.diff()
@@ -27,36 +91,11 @@ def compute_rsi(series, period=14):
27
  rs = gain / loss
28
  return 100 - (100 / (1 + rs))
29
 
30
- def load_csv_from_url(url):
31
- try:
32
- headers = {"User-Agent": "Mozilla/5.0"}
33
- r = requests.get(url, headers=headers, timeout=20)
34
- r.raise_for_status()
35
- df = pd.read_csv(io.StringIO(r.text))
36
- return df, None
37
- except Exception as e:
38
- return None, f"CSV indirilemedi: {e}"
39
-
40
- def process_dataframe(df):
41
- df.columns = [c.strip().lower() for c in df.columns]
42
- col_map = {
43
- "date": "date", "datetime": "date", "timestamp": "date",
44
- "open": "open", "high": "high", "low": "low",
45
- "close": "close", "adj close": "close", "price": "close",
46
- "volume": "volume", "vol": "volume"
47
- }
48
- df = df.rename(columns={c: col_map[c] for c in df.columns if c in col_map})
49
-
50
- if "close" not in df.columns:
51
- return None, None, None, f"'close' sütunu bulunamadı. Mevcut sütunlar: {list(df.columns)}"
52
-
53
- for col in ["open", "high", "low", "close", "volume"]:
54
- if col in df.columns:
55
- df[col] = pd.to_numeric(df[col], errors="coerce")
56
-
57
- df = df.dropna(subset=["close"]).reset_index(drop=True)
58
- if len(df) < 50:
59
- return None, None, None, "CSV'de en az 50 satır veri olmalı."
60
 
61
  # Teknik göstergeler
62
  df["ma_5"] = df["close"].rolling(5).mean()
@@ -67,72 +106,74 @@ def process_dataframe(df):
67
 
68
  df_model = df.dropna().reset_index(drop=True)
69
  if len(df_model) < 20:
70
- return None, None, None, "Göstergeler hesaplandıktan sonra yeterli veri kalmadı."
71
-
72
- features = ["ma_5", "ma_20", "rsi", "macd"]
73
- if "volume" in df_model.columns:
74
- features.append("volume")
75
 
 
76
  X = df_model[features].values
77
  y = df_model["target"].values
78
 
79
- # --- XGBoost ---
80
  xgb_model = xgb.XGBClassifier(
81
  n_estimators=50, max_depth=3, learning_rate=0.1,
82
  objective="binary:logistic", eval_metric="logloss", random_state=42
83
  )
84
  xgb_model.fit(X, y)
85
 
86
- # --- KNN (ölçeklendirme gerekli) ---
87
  scaler = StandardScaler()
88
  X_scaled = scaler.fit_transform(X)
89
  knn_model = KNeighborsClassifier(n_neighbors=5)
90
  knn_model.fit(X_scaled, y)
91
 
92
- latest = df_model.iloc[-1]
93
- metrics = {
94
- "last_close": float(latest["close"]),
95
- "ma5": float(latest["ma_5"]),
96
- "ma20": float(latest["ma_20"]),
97
- "rsi": float(latest["rsi"]),
98
- "macd": float(latest["macd"]),
99
- "features": features,
100
- }
101
- if "volume" in df_model.columns:
102
- metrics["volume"] = float(latest["volume"])
103
 
104
- return (xgb_model, knn_model, scaler), metrics, features, None
 
 
 
 
 
 
 
 
 
 
 
105
 
106
  # ==========================================
107
- # 🧠 3. ANALİZ MOTORU (Ensemble: XGB + KNN)
108
  # ==========================================
109
- def predict_and_analyze(csv_url):
110
- if not csv_url:
111
- return "Lütfen bir CSV linki giriniz.", {}
 
112
 
113
- df, err = load_csv_from_url(csv_url)
114
- if err:
115
- return err, {}
116
 
117
- models, metrics, features, err = process_dataframe(df)
118
- if err:
119
- return err, {}
120
 
121
- xgb_model, knn_model, scaler = models
 
 
 
 
 
122
 
123
- feat_values = [metrics[k] for k in ["ma5", "ma20", "rsi", "macd"]]
124
- if "volume" in metrics:
125
- feat_values.append(metrics["volume"])
126
- feat_arr = np.array([feat_values])
127
 
128
- # XGBoost tahmini
129
  xgb_prob_up = float(xgb_model.predict_proba(feat_arr)[0][1])
130
 
131
- # KNN tahmini (ölçeklendirilmiş veriyle)
132
  feat_scaled = scaler.transform(feat_arr)
133
  knn_prob_up = float(knn_model.predict_proba(feat_scaled)[0][1])
134
 
135
- # Ensemble (ortalama)
136
  ensemble_prob_up = (xgb_prob_up + knn_prob_up) / 2
137
  ensemble_prob_down = 1 - ensemble_prob_up
138
 
@@ -148,11 +189,16 @@ def predict_and_analyze(csv_url):
148
  prompt = f"""
149
  Sen uzman bir kripto para analisti ve teknik analiz uzmanısın.
150
 
151
- 📊 BTC/USD Son Kapanış (CSV'den): ${metrics['last_close']:,.2f}
152
- - RSI (14): {metrics['rsi']:.2f}
153
- - MA5: ${metrics['ma5']:,.2f} | MA20: ${metrics['ma20']:,.2f}
154
- - MACD: {metrics['macd']:.4f}
155
- {f"- Hacim: {metrics['volume']:,.2f}" if 'volume' in metrics else ""}
 
 
 
 
 
156
 
157
  🤖 Model Sonuçları:
158
  - XGBoost Yükseliş Olasılığı: %{xgb_prob_up*100:.1f}
@@ -161,7 +207,7 @@ def predict_and_analyze(csv_url):
161
  - Tahmin Yönü: {direction} (Güven: %{confidence:.1f})
162
 
163
  Türkçe bir teknik analiz raporu hazırla. Şu başlıklar bulunsun:
164
- 1. 🎯 Model Yorumu (XGBoost ve KNN'in karşılaştırmalı mantığı, ensemble neden kullanılır)
165
  2. 📈 Teknik Analiz (RSI, MA, MACD; destek/direnç)
166
  3. 💡 İşlem Stratejisi (Long/Short, stop-loss, take-profit, risk yönetimi)
167
 
@@ -183,49 +229,40 @@ def predict_and_analyze(csv_url):
183
  analysis_result = "GROQ_API_KEY bulunamadı! Hugging Face Secrets'a ekleyin."
184
 
185
  header = (
186
- f"**Son Kapanış: ${metrics['last_close']:,.2f}** | RSI: {metrics['rsi']:.1f} | "
187
- f"MA5: ${metrics['ma5']:,.0f} | MA20: ${metrics['ma20']:,.0f}\n\n"
188
  f"**XGB:** %{xgb_prob_up*100:.1f} | **KNN:** %{knn_prob_up*100:.1f} | "
189
  f"**Ensemble:** %{ensemble_prob_up*100:.1f}\n\n---\n\n"
190
  )
191
  return header + analysis_result, prob_dict
192
 
193
  # ==========================================
194
- # 🎨 4. GRADIO ARAYÜZÜ
195
  # ==========================================
196
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", secondary_hue="slate")) as demo:
197
  gr.Markdown(
198
  """
199
- # ₿ BTC/USD XGBoost + KNN & Groq AI Tahmin Radarı (CSV Linki)
200
- Bir CSV linki girin; kod dosyayı indirir, **XGBoost** ve **KNN** modellerini eğitir, ensemble tahmini üretir ve **Groq** analiz raporu hazırlar.
201
  """
202
  )
203
 
204
  with gr.Row():
205
  with gr.Column():
206
- gr.Markdown("### 🔗 CSV Linki")
207
- url_input = gr.Textbox(
208
- label="CSV URL",
209
- placeholder="https://.../btc_usd.csv",
210
- value=""
211
- )
212
  gr.Markdown(
213
  """
214
- **İpucu**: `yfinance` ile indirdiğiniz CSV'yi GitHub'a yükleyip "Raw" linkini buraya yapıştırın.
215
  """
216
  )
217
- submit_btn = gr.Button("CSV'yi İndir ve Analiz Et", variant="primary")
218
 
219
  with gr.Column():
220
- gr.Markdown("### 📈 Model Tahminleri (XGB + KNN)")
221
- prob_output = gr.Label(label="Olasılık Dağılımı")
222
-
223
- gr.Markdown("### 🧠 Groq Yapay Zeka Analiz Raporu")
224
- analysis_output = gr.Markdown(value="CSV linkini girip butona basın.")
225
 
226
- submit_btn.click(
227
  fn=predict_and_analyze,
228
- inputs=[url_input],
229
  outputs=[analysis_output, prob_output]
230
  )
231
 
 
1
  import os
2
+ import time
3
  import requests
4
  import numpy as np
5
  import pandas as pd
 
18
  client = Groq(api_key=api_key)
19
 
20
  # ==========================================
21
+ # 📡 2. OKX PUBLIC API (Cloudflare engelini aşmak için)
22
+ # ==========================================
23
+ OKX_BASE = "https://www.okx.com/api/v5"
24
+
25
+ # Cloudflare'in bot algılamasını azaltmak için tarayıcı benzeri başlıklar
26
+ OKX_HEADERS = {
27
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
28
+ "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
29
+ "Accept": "application/json",
30
+ "Accept-Language": "en-US,en;q=0.9",
31
+ }
32
+
33
+ def fetch_okx_ticker(inst_id="BTC-USDT"):
34
+ """OKX'ten anlık fiyat çeker. 3 kez dener, başarısızsa None döner."""
35
+ for attempt in range(3):
36
+ try:
37
+ r = requests.get(
38
+ f"{OKX_BASE}/market/ticker",
39
+ params={"instId": inst_id},
40
+ headers=OKX_HEADERS,
41
+ timeout=15
42
+ )
43
+ r.raise_for_status()
44
+ d = r.json()["data"][0]
45
+ return {
46
+ "last": float(d["last"]),
47
+ "open24h": float(d["open24h"]),
48
+ "high24h": float(d["high24h"]),
49
+ "low24h": float(d["low24h"]),
50
+ "vol24h": float(d["vol24h"]),
51
+ "change_pct": (float(d["last"]) / float(d["open24h"]) - 1) * 100
52
+ }
53
+ except Exception as e:
54
+ print(f"OKX ticker attempt {attempt+1} failed: {e}")
55
+ if attempt < 2:
56
+ time.sleep(2)
57
+ return None
58
+
59
+ def fetch_okx_candles(inst_id="BTC-USDT", bar="1H", limit=100):
60
+ """OKX'ten mum verisi çeker. 3 kez dener, başarısızsa None döner."""
61
+ for attempt in range(3):
62
+ try:
63
+ r = requests.get(
64
+ f"{OKX_BASE}/market/candles",
65
+ params={"instId": inst_id, "bar": bar, "limit": limit},
66
+ headers=OKX_HEADERS,
67
+ timeout=15
68
+ )
69
+ r.raise_for_status()
70
+ raw = r.json()["data"]
71
+ # OKX mum formatı: [ts, open, high, low, close, vol, ...]
72
+ df = pd.DataFrame(raw, columns=["ts", "open", "high", "low", "close", "vol"])
73
+ for col in ["open", "high", "low", "close", "vol"]:
74
+ df[col] = df[col].astype(float)
75
+ df["ts"] = pd.to_datetime(df["ts"].astype(int), unit="ms")
76
+ df = df.sort_values("ts").reset_index(drop=True)
77
+ return df
78
+ except Exception as e:
79
+ print(f"OKX candles attempt {attempt+1} failed: {e}")
80
+ if attempt < 2:
81
+ time.sleep(2)
82
+ return None
83
+
84
+ # ==========================================
85
+ # 📊 3. YARDIMCI FONKSİYONLAR
86
  # ==========================================
87
  def compute_rsi(series, period=14):
88
  delta = series.diff()
 
91
  rs = gain / loss
92
  return 100 - (100 / (1 + rs))
93
 
94
+ def train_models_from_okx():
95
+ """OKX'ten çekilen mum verisiyle XGBoost ve KNN modellerini eğitir."""
96
+ df = fetch_okx_candles(limit=500)
97
+ if df is None or len(df) < 50:
98
+ return None, None, None, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  # Teknik göstergeler
101
  df["ma_5"] = df["close"].rolling(5).mean()
 
106
 
107
  df_model = df.dropna().reset_index(drop=True)
108
  if len(df_model) < 20:
109
+ return None, None, None, None
 
 
 
 
110
 
111
+ features = ["ma_5", "ma_20", "rsi", "macd", "vol"]
112
  X = df_model[features].values
113
  y = df_model["target"].values
114
 
115
+ # XGBoost
116
  xgb_model = xgb.XGBClassifier(
117
  n_estimators=50, max_depth=3, learning_rate=0.1,
118
  objective="binary:logistic", eval_metric="logloss", random_state=42
119
  )
120
  xgb_model.fit(X, y)
121
 
122
+ # KNN (ölçeklendirme gerekli)
123
  scaler = StandardScaler()
124
  X_scaled = scaler.fit_transform(X)
125
  knn_model = KNeighborsClassifier(n_neighbors=5)
126
  knn_model.fit(X_scaled, y)
127
 
128
+ return xgb_model, knn_model, scaler, features
129
+
130
+ # Başlangıçta modelleri OKX verisiyle eğit
131
+ xgb_model, knn_model, scaler, feature_cols = train_models_from_okx()
 
 
 
 
 
 
 
132
 
133
+ if xgb_model is None:
134
+ # OKX erişilemezse fallback: basit dummy modeller
135
+ print("OKX erişilemedi, dummy modeller kullanılıyor.")
136
+ dummy_X = np.random.rand(50, 5)
137
+ dummy_y = np.random.randint(0, 2, 50)
138
+ xgb_model = xgb.XGBClassifier(n_estimators=10, max_depth=2)
139
+ xgb_model.fit(dummy_X, dummy_y)
140
+ scaler = StandardScaler()
141
+ dummy_X_scaled = scaler.fit_transform(dummy_X)
142
+ knn_model = KNeighborsClassifier(n_neighbors=5)
143
+ knn_model.fit(dummy_X_scaled, dummy_y)
144
+ feature_cols = ["ma_5", "ma_20", "rsi", "macd", "vol"]
145
 
146
  # ==========================================
147
+ # 🧠 4. ANALİZ MOTORU (XGB + KNN Ensemble)
148
  # ==========================================
149
+ def predict_and_analyze():
150
+ # 1) OKX'ten canlı veri çek
151
+ ticker = fetch_okx_ticker()
152
+ candles = fetch_okx_candles(limit=30)
153
 
154
+ if ticker is None or candles is None:
155
+ return "❌ OKX API'sine erişilemedi. Cloudflare engellemesi olabilir. Lütfen daha sonra tekrar deneyin.", {}
 
156
 
157
+ last_price = ticker["last"]
158
+ change_pct = ticker["change_pct"]
159
+ vol24h = ticker["vol24h"]
160
 
161
+ # 2) Teknik göstergeler
162
+ close = candles["close"]
163
+ ma5 = close.rolling(5).mean().iloc[-1]
164
+ ma20 = close.rolling(20).mean().iloc[-1]
165
+ rsi = compute_rsi(close, 14).iloc[-1]
166
+ macd = (close.ewm(span=12).mean() - close.ewm(span=26).mean()).iloc[-1]
167
 
168
+ # 3) XGBoost ve KNN tahminleri
169
+ feat_arr = np.array([[ma5, ma20, rsi, macd, vol24h]])
 
 
170
 
 
171
  xgb_prob_up = float(xgb_model.predict_proba(feat_arr)[0][1])
172
 
 
173
  feat_scaled = scaler.transform(feat_arr)
174
  knn_prob_up = float(knn_model.predict_proba(feat_scaled)[0][1])
175
 
176
+ # 4) Ensemble (ortalama)
177
  ensemble_prob_up = (xgb_prob_up + knn_prob_up) / 2
178
  ensemble_prob_down = 1 - ensemble_prob_up
179
 
 
189
  prompt = f"""
190
  Sen uzman bir kripto para analisti ve teknik analiz uzmanısın.
191
 
192
+ 📡 OKX Canlı Verileri (BTC/USDT):
193
+ - Son Fiyat: ${last_price:,.2f}
194
+ - 24s Değişim: %{change_pct:+.2f}
195
+ - 24s Hacim: {vol24h:,.0f} BTC
196
+ - 24s Yüksek/Düşük: ${ticker['high24h']:,.2f} / ${ticker['low24h']:,.2f}
197
+
198
+ 📊 Teknik Göstergeler (1H):
199
+ - RSI (14): {rsi:.2f}
200
+ - MA5: ${ma5:,.2f} | MA20: ${ma20:,.2f}
201
+ - MACD: {macd:.4f}
202
 
203
  🤖 Model Sonuçları:
204
  - XGBoost Yükseliş Olasılığı: %{xgb_prob_up*100:.1f}
 
207
  - Tahmin Yönü: {direction} (Güven: %{confidence:.1f})
208
 
209
  Türkçe bir teknik analiz raporu hazırla. Şu başlıklar bulunsun:
210
+ 1. 🎯 Model Yorumu (XGBoost ve KNN'in karşılaştırmalı mantığı)
211
  2. 📈 Teknik Analiz (RSI, MA, MACD; destek/direnç)
212
  3. 💡 İşlem Stratejisi (Long/Short, stop-loss, take-profit, risk yönetimi)
213
 
 
229
  analysis_result = "GROQ_API_KEY bulunamadı! Hugging Face Secrets'a ekleyin."
230
 
231
  header = (
232
+ f"**OKX Canlı: ${last_price:,.2f}** (%{change_pct:+.2f}) | RSI: {rsi:.1f} | "
233
+ f"MA5: ${ma5:,.0f} | MA20: ${ma20:,.0f}\n\n"
234
  f"**XGB:** %{xgb_prob_up*100:.1f} | **KNN:** %{knn_prob_up*100:.1f} | "
235
  f"**Ensemble:** %{ensemble_prob_up*100:.1f}\n\n---\n\n"
236
  )
237
  return header + analysis_result, prob_dict
238
 
239
  # ==========================================
240
+ # 🎨 5. GRADIO ARAYÜZÜ
241
  # ==========================================
242
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", secondary_hue="slate")) as demo:
243
  gr.Markdown(
244
  """
245
+ # ₿ BTC/USD XGBoost + KNN & Groq AI Tahmin Radarı (OKX Canlı)
246
+ Fiyat ve mum verileri **OKX halka açık API**'sinden otomatik çekilir. **XGBoost + KNN** ensemble tahmini yapar, **Groq** analiz raporu üretir.
247
  """
248
  )
249
 
250
  with gr.Row():
251
  with gr.Column():
252
+ analyze_btn = gr.Button("🔄 OKX'ten Veri Çek ve Analiz Et", variant="primary", size="lg")
 
 
 
 
 
253
  gr.Markdown(
254
  """
255
+ **Not**: OKX API'si Cloudflare koruması altındadır. Kod, tarayıcı benzeri User-Agent ve 3 deneme mekanizması içerir.
256
  """
257
  )
 
258
 
259
  with gr.Column():
260
+ prob_output = gr.Label(label="Model Tahminleri (XGB + KNN)")
261
+ analysis_output = gr.Markdown(value="Butona basarak OKX'ten canlı veri çekip analizi başlatın.")
 
 
 
262
 
263
+ analyze_btn.click(
264
  fn=predict_and_analyze,
265
+ inputs=[],
266
  outputs=[analysis_output, prob_output]
267
  )
268