GoshawkVortexAI commited on
Commit
b13d96c
·
verified ·
1 Parent(s): e2517d4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +195 -201
app.py CHANGED
@@ -1,227 +1,221 @@
1
- import os
2
- import io
 
 
 
 
3
  import requests
4
- import numpy as np
5
  import pandas as pd
6
  import gradio as gr
7
- import xgboost as xgb
8
- from groq import Groq
9
-
10
- # ==========================================
11
- # 🔌 1. GROQ CLIENT
12
- # ==========================================
13
- api_key = os.environ.get("GROQ_API_KEY")
14
- client = None
15
- if api_key:
16
- client = Groq(api_key=api_key)
17
-
18
- # ==========================================
19
- # 📊 2. YARDIMCI FONKSİYONLAR
20
- # ==========================================
21
- def compute_rsi(series, period=14):
22
- delta = series.diff()
23
- gain = delta.clip(lower=0).rolling(period).mean()
24
- loss = -delta.clip(upper=0).rolling(period).mean()
25
- rs = gain / loss
26
- return 100 - (100 / (1 + rs))
27
-
28
- def load_csv_from_url(url):
29
- """Verilen URL'den CSV indirir ve DataFrame döndürür."""
30
  try:
31
- headers = {"User-Agent": "Mozilla/5.0"}
32
- r = requests.get(url, headers=headers, timeout=20)
33
- r.raise_for_status()
34
- df = pd.read_csv(io.StringIO(r.text))
35
- return df, None
36
- except Exception as e:
37
- return None, f"CSV indirilemedi: {e}"
38
 
39
- def process_dataframe(df):
40
- """CSV DataFrame'ini işler, göstergeleri hesaplar ve XGBoost modelini eğitir."""
41
- df.columns = [c.strip().lower() for c in df.columns]
42
 
43
- # Sütun eşleştirme (farklı CSV formatlarına tolerans)
44
- col_map = {
45
- "date": "date", "datetime": "date", "timestamp": "date",
46
- "open": "open", "high": "high", "low": "low",
47
- "close": "close", "adj close": "close", "price": "close",
48
- "volume": "volume", "vol": "volume"
49
- }
50
- df = df.rename(columns={c: col_map[c] for c in df.columns if c in col_map})
51
 
52
- if "close" not in df.columns:
53
- return None, None, f"'close' sütunu bulunamadı. Mevcut sütunlar: {list(df.columns)}"
 
54
 
55
- for col in ["open", "high", "low", "close", "volume"]:
56
- if col in df.columns:
57
- df[col] = pd.to_numeric(df[col], errors="coerce")
58
 
59
- df = df.dropna(subset=["close"]).reset_index(drop=True)
60
 
61
- if len(df) < 50:
62
- return None, None, "CSV'de en az 50 satır veri olmalı."
 
 
 
63
 
64
- # Teknik göstergeler
65
- df["ma_5"] = df["close"].rolling(5).mean()
66
- df["ma_20"] = df["close"].rolling(20).mean()
67
- df["rsi"] = compute_rsi(df["close"], 14)
68
- df["macd"] = df["close"].ewm(span=12).mean() - df["close"].ewm(span=26).mean()
69
- df["target"] = (df["close"].shift(-1) > df["close"]).astype(int)
70
 
71
- df_model = df.dropna().reset_index(drop=True)
 
 
 
 
72
 
73
- if len(df_model) < 20:
74
- return None, None, "Göstergeler hesaplandıktan sonra yeterli veri kalmadı."
75
 
76
- features = ["ma_5", "ma_20", "rsi", "macd"]
77
- if "volume" in df_model.columns:
78
- features.append("volume")
79
 
80
- X = df_model[features]
81
- y = df_model["target"]
82
 
83
- model = xgb.XGBClassifier(
84
- n_estimators=50, max_depth=3, learning_rate=0.1,
85
- objective="binary:logistic", eval_metric="logloss", random_state=42
86
- )
87
- model.fit(X, y)
88
-
89
- latest = df_model.iloc[-1]
90
- metrics = {
91
- "last_close": float(latest["close"]),
92
- "ma5": float(latest["ma_5"]),
93
- "ma20": float(latest["ma_20"]),
94
- "rsi": float(latest["rsi"]),
95
- "macd": float(latest["macd"]),
96
- "features": features,
97
- }
98
- if "volume" in df_model.columns:
99
- metrics["volume"] = float(latest["volume"])
100
-
101
- return model, metrics, None
102
-
103
- # ==========================================
104
- # 🧠 3. ANALİZ MOTORU
105
- # ==========================================
106
- def predict_and_analyze(csv_url):
107
- if not csv_url:
108
- return "Lütfen bir CSV linki giriniz.", {}
109
-
110
- # 1) CSV indir
111
- df, err = load_csv_from_url(csv_url)
112
- if err:
113
- return err, {}
114
-
115
- # 2) Modeli eğit
116
- model, metrics, err = process_dataframe(df)
117
- if err:
118
- return err, {}
119
-
120
- # 3) Tahmin
121
- feat_values = [metrics[k] for k in ["ma5", "ma20", "rsi", "macd"]]
122
- if "volume" in metrics:
123
- feat_values.append(metrics["volume"])
124
- features_arr = np.array([feat_values])
125
- prob_up = float(model.predict_proba(features_arr)[0][1])
126
- prob_down = 1 - prob_up
127
-
128
- direction = "YUKARI 📈" if prob_up > 0.5 else "AŞAĞI 📉"
129
- confidence = max(prob_up, prob_down) * 100
130
-
131
- prob_dict = {
132
- "Yükseliş (Long) Olasılığı": prob_up,
133
- "Düşüş (Short) Olasılığı": prob_down,
134
- }
135
-
136
- prompt = f"""
137
- Sen uzman bir kripto para analisti ve teknik analiz uzmanısın.
138
-
139
- 📊 BTC/USD Son Kapanış (CSV'den): ${metrics['last_close']:,.2f}
140
- - RSI (14): {metrics['rsi']:.2f}
141
- - MA5: ${metrics['ma5']:,.2f} | MA20: ${metrics['ma20']:,.2f}
142
- - MACD: {metrics['macd']:.4f}
143
- {f"- Hacim: {metrics['volume']:,.2f}" if 'volume' in metrics else ""}
144
-
145
- 🤖 XGBoost Model Sonucu:
146
- - Yükseliş Olasılığı: %{prob_up*100:.1f}
147
- - Düşüş Olasılığı: %{prob_down*100:.1f}
148
- - Tahmin Yönü: {direction} (Güven: %{confidence:.1f})
149
-
150
- Türkçe bir teknik analiz raporu hazırla. Şu başlıklar bulunsun:
151
- 1. 🎯 Model Yorumu (XGBoost + teknik göstergelerin mantığı)
152
- 2. 📈 Teknik Analiz (RSI, MA, MACD; destek/direnç)
153
- 3. 💡 İşlem Stratejisi (Long/Short, stop-loss, take-profit, risk yönetimi)
154
-
155
- Yatırım tavsiyesi olmadığını vurgula. Rasyonel ve profesyonel ol.
156
- """
157
-
158
- if client:
159
- try:
160
- response = client.chat.completions.create(
161
- model="openai/gpt-oss-120b",
162
- messages=[{"role": "user", "content": prompt}],
163
- temperature=0.3,
164
- max_tokens=1024
165
  )
166
- analysis_result = response.choices[0].message.content
167
- except Exception as e:
168
- analysis_result = f"Groq API Hatası: {e}"
169
- else:
170
- analysis_result = "GROQ_API_KEY bulunamadı! Hugging Face Secrets'a ekleyin."
171
-
172
- header = (
173
- f"**CSV: Son Kapanış ${metrics['last_close']:,.2f}** | RSI: {metrics['rsi']:.1f} | "
174
- f"MA5: ${metrics['ma5']:,.0f} | MA20: ${metrics['ma20']:,.0f}\n\n---\n\n"
175
- )
176
- return header + analysis_result, prob_dict
177
-
178
- # ==========================================
179
- # 🎨 4. GRADIO ARAYÜZÜ
180
- # ==========================================
181
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", secondary_hue="slate")) as demo:
182
- gr.Markdown(
183
- """
184
- # ₿ BTC/USD XGBoost & Groq AI Tahmin Radarı (CSV Linki)
185
- Bir CSV linki girin; kod dosyayı indirir, göstergeleri hesaplar, **XGBoost** modelini eğitir ve **Groq** analiz raporu üretir.
186
- """
187
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
 
189
  with gr.Row():
190
- with gr.Column():
191
- gr.Markdown("### 🔗 CSV Linki")
192
- url_input = gr.Textbox(
193
- label="CSV URL",
194
- placeholder="https://.../btc_usd.csv",
195
- value=""
196
- )
197
- gr.Markdown(
198
- """
199
- **Örnek linkler:**
200
- - `https://raw.githubusercontent.com/.../btc_usd.csv`
201
- - Kaggle'dan indirdiğiniz CSV'yi GitHub'a yükleyip raw linkini kullanabilirsiniz.
202
- """
203
- )
204
- submit_btn = gr.Button("CSV'yi İndir ve Analiz Et", variant="primary")
 
 
 
 
 
 
 
 
205
 
206
- with gr.Column():
207
- gr.Markdown("### 📈 XGBoost Yön Tahmini")
208
- prob_output = gr.Label(label="Olasılık Dağılımı")
209
 
210
- gr.Markdown("### 🧠 Groq Yapay Zeka Analiz Raporu")
211
- analysis_output = gr.Markdown(value="CSV linkini girip butona basın.")
212
 
213
- submit_btn.click(
214
- fn=predict_and_analyze,
215
- inputs=[url_input],
216
- outputs=[analysis_output, prob_output]
217
  )
218
 
219
- gr.Markdown(
220
- """
221
- ---
222
- ⚠️ **Yatırım Tavsiyesi Değildir**: Bu uygulama eğitim amaçlıdır.
223
- """
224
  )
225
 
226
- if __name__ == "__main__":
227
- demo.launch()
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # app.py
3
+ # OKX BTC-USDT Historical Data Downloader
4
+ # Gradio + OKX Public API + CSV
5
+
6
+ import time
7
  import requests
 
8
  import pandas as pd
9
  import gradio as gr
10
+ import tempfile
11
+ import os
12
+ from datetime import datetime, timedelta, timezone
13
+
14
+ API_URL = "https://www.okx.com/api/v5/market/history-candles"
15
+
16
+ TIMEFRAMES = [
17
+ "1m", "3m", "5m", "15m", "30m",
18
+ "1H", "2H", "4H", "6H", "12H", "1D"
19
+ ]
20
+
21
+ def download_data(days, timeframe, symbol, progress=gr.Progress()):
22
+
 
 
 
 
 
 
 
 
 
 
23
  try:
24
+ days = int(days)
25
+ symbol = symbol.strip().upper()
26
+
27
+ if not symbol:
28
+ raise ValueError("Trading pair boş olamaz.")
 
 
29
 
30
+ end_time = datetime.now(timezone.utc)
31
+ start_time = end_time - timedelta(days=days)
 
32
 
33
+ start_ms = int(start_time.timestamp() * 1000)
 
 
 
 
 
 
 
34
 
35
+ all_data = []
36
+ after = None
37
+ seen = set()
38
 
39
+ session = requests.Session()
 
 
40
 
41
+ while True:
42
 
43
+ params = {
44
+ "instId": symbol,
45
+ "bar": timeframe,
46
+ "limit": "300"
47
+ }
48
 
49
+ if after is not None:
50
+ params["after"] = str(after)
 
 
 
 
51
 
52
+ response = session.get(
53
+ API_URL,
54
+ params=params,
55
+ timeout=30
56
+ )
57
 
58
+ response.raise_for_status()
59
+ result = response.json()
60
 
61
+ if result.get("code") != "0":
62
+ raise RuntimeError(result.get("msg", "OKX API error"))
 
63
 
64
+ data = result.get("data", [])
 
65
 
66
+ if not data:
67
+ break
68
+
69
+ new_count = 0
70
+
71
+ for candle in data:
72
+ timestamp = int(candle[0])
73
+
74
+ if timestamp < start_ms:
75
+ continue
76
+
77
+ if timestamp not in seen:
78
+ seen.add(timestamp)
79
+ all_data.append(candle)
80
+ new_count += 1
81
+
82
+ oldest = min(int(x[0]) for x in data)
83
+
84
+ progress(
85
+ min(0.99, max(0.01,
86
+ 1 - (oldest - start_ms) /
87
+ max(1, int(end_time.timestamp() * 1000) - start_ms))),
88
+ desc=f"Veri çekiliyor: {len(all_data)} mum"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  )
90
+
91
+ if oldest <= start_ms:
92
+ break
93
+
94
+ if new_count == 0 and after == oldest:
95
+ break
96
+
97
+ after = oldest
98
+
99
+ time.sleep(0.12)
100
+
101
+ if not all_data:
102
+ raise ValueError("Veri bulunamadı.")
103
+
104
+ columns = [
105
+ "timestamp", "open", "high", "low", "close",
106
+ "volume", "volume_currency", "volume_quote",
107
+ "confirm"
108
+ ]
109
+
110
+ df = pd.DataFrame(all_data, columns=columns)
111
+
112
+ df["timestamp"] = pd.to_datetime(
113
+ pd.to_numeric(df["timestamp"]),
114
+ unit="ms",
115
+ utc=True
116
+ )
117
+
118
+ numeric_columns = [
119
+ "open", "high", "low", "close",
120
+ "volume", "volume_currency", "volume_quote"
121
+ ]
122
+
123
+ for col in numeric_columns:
124
+ df[col] = pd.to_numeric(df[col])
125
+
126
+ df["confirm"] = pd.to_numeric(df["confirm"])
127
+
128
+ df = df.sort_values("timestamp")
129
+ df = df.drop_duplicates(subset=["timestamp"])
130
+ df = df.reset_index(drop=True)
131
+
132
+ temp = tempfile.NamedTemporaryFile(
133
+ suffix=".csv",
134
+ prefix="BTCUSD_OKX_",
135
+ delete=False
136
+ )
137
+
138
+ file_path = temp.name
139
+ temp.close()
140
+
141
+ df.to_csv(file_path, index=False)
142
+
143
+ summary = f"""
144
+ ### İndirme tamamlandı
145
+
146
+ - Sembol: {symbol}
147
+ - Zaman aralığı: {timeframe}
148
+ - İstenen geçmiş: {days} gün
149
+ - Toplam mum: {len(df)}
150
+ - İlk tarih: {df['timestamp'].min()}
151
+ - Son tarih: {df['timestamp'].max()}
152
+ - CSV boyutu: {os.path.getsize(file_path) / 1024:.2f} KB
153
+ """
154
+
155
+ return file_path, summary, df.tail(20)
156
+
157
+ except Exception as e:
158
+ return None, f"Hata: {str(e)}", pd.DataFrame()
159
+
160
+
161
+ with gr.Blocks(title="OKX BTCUSD Data Downloader") as demo:
162
+
163
+ gr.Markdown("""
164
+ # OKX BTC-USDT Data Downloader
165
+
166
+ OKX Public API üzerinden geçmiş kripto para verilerini indir.
167
+
168
+ API Key gerekmez.
169
+ """)
170
 
171
  with gr.Row():
172
+ symbol = gr.Textbox(
173
+ label="Trading Pair",
174
+ value="BTC-USDT"
175
+ )
176
+
177
+ timeframe = gr.Dropdown(
178
+ choices=TIMEFRAMES,
179
+ value="1H",
180
+ label="Timeframe"
181
+ )
182
+
183
+ days = gr.Slider(
184
+ minimum=1,
185
+ maximum=90,
186
+ value=30,
187
+ step=1,
188
+ label="Geçmiş Gün"
189
+ )
190
+
191
+ download_btn = gr.Button(
192
+ "BTC Verilerini İndir",
193
+ variant="primary"
194
+ )
195
 
196
+ output_file = gr.File(label="CSV Dosyası")
 
 
197
 
198
+ status = gr.Markdown()
 
199
 
200
+ preview = gr.Dataframe(
201
+ label="Son 20 Mum",
202
+ interactive=False
 
203
  )
204
 
205
+ download_btn.click(
206
+ fn=download_data,
207
+ inputs=[days, timeframe, symbol],
208
+ outputs=[output_file, status, preview]
 
209
  )
210
 
211
+ gr.Markdown("""
212
+ **Veri:** OKX Public Market API
213
+
214
+ **CSV sütunları:** Timestamp, Open, High, Low,
215
+ Close, Volume, Volume Currency, Volume Quote, Confirm.
216
+
217
+ Not: OKX BTC-USDT spot verisidir; BTC-USD ile aynı
218
+ işlem çifti değildir. USDT bazlı fiyat kullanır.
219
+ """)
220
+
221
+ demo.queue().launch(server_name="0.0.0.0", server_port=7860)