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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +342 -127
app.py CHANGED
@@ -1,181 +1,389 @@
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
  )
@@ -185,37 +393,44 @@ with gr.Blocks(title="OKX BTCUSD Data Downloader") as demo:
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)
 
 
 
 
1
 
2
+ import os
 
 
 
3
  import time
4
+ import tempfile
5
  import requests
6
  import pandas as pd
7
  import gradio as gr
8
+
 
9
  from datetime import datetime, timedelta, timezone
10
+ from groq import Groq
11
 
12
+ # =====================================
13
+ # CONFIG
14
+ # =====================================
15
 
16
+ OKX_URL = "https://www.okx.com/api/v5/market/history-candles"
 
 
 
17
 
18
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
19
 
20
+ GROQ_MODEL = os.getenv(
21
+ "GROQ_MODEL",
22
+ "llama-3.3-70b-versatile"
23
+ )
24
 
25
+ # =====================================
26
+ # OKX DATA ENGINE
27
+ # =====================================
28
 
29
+ def get_okx_data(days, timeframe, symbol, progress=gr.Progress()):
 
30
 
31
+ days = int(days)
32
+ symbol = symbol.strip().upper()
33
 
34
+ if not symbol:
35
+ raise ValueError("Trading pair gerekli.")
 
36
 
37
+ end = datetime.now(timezone.utc)
38
+ start = end - timedelta(days=days)
39
 
40
+ start_ms = int(start.timestamp() * 1000)
41
+ end_ms = int(end.timestamp() * 1000)
42
 
43
+ all_data = []
44
+ seen = set()
45
+ after = None
 
 
46
 
47
+ session = requests.Session()
 
48
 
49
+ while True:
 
 
 
 
50
 
51
+ params = {
52
+ "instId": symbol,
53
+ "bar": timeframe,
54
+ "limit": "300"
55
+ }
56
 
57
+ if after is not None:
58
+ params["after"] = str(after)
59
 
60
+ response = session.get(
61
+ OKX_URL,
62
+ params=params,
63
+ timeout=30
64
+ )
65
 
66
+ response.raise_for_status()
 
67
 
68
+ result = response.json()
69
 
70
+ if result.get("code") != "0":
71
+ raise RuntimeError(result.get("msg", "OKX API error"))
72
 
73
+ data = result.get("data", [])
 
74
 
75
+ if not data:
76
+ break
 
 
77
 
78
+ for candle in data:
79
 
80
+ ts = int(candle[0])
 
 
 
 
 
81
 
82
+ if start_ms <= ts <= end_ms and ts not in seen:
83
+ seen.add(ts)
84
+ all_data.append(candle)
85
 
86
+ oldest = min(int(x[0]) for x in data)
 
87
 
88
+ progress(
89
+ min(
90
+ 0.99,
91
+ max(
92
+ 0.01,
93
+ 1 - (oldest - start_ms) /
94
+ max(1, end_ms - start_ms)
95
+ )
96
+ ),
97
+ desc=f"OKX verisi: {len(all_data)} mum"
98
+ )
99
 
100
+ if oldest <= start_ms:
101
+ break
102
 
103
+ after = oldest
 
104
 
105
+ time.sleep(0.15)
106
+
107
+ if not all_data:
108
+ raise ValueError("OKX verisi bulunamadı.")
109
+
110
+ columns = [
111
+ "timestamp",
112
+ "open",
113
+ "high",
114
+ "low",
115
+ "close",
116
+ "volume",
117
+ "volume_currency",
118
+ "volume_quote",
119
+ "confirm"
120
+ ]
121
+
122
+ df = pd.DataFrame(all_data, columns=columns)
123
+
124
+ df["timestamp"] = pd.to_datetime(
125
+ df["timestamp"].astype("int64"),
126
+ unit="ms",
127
+ utc=True
128
+ )
129
+
130
+ numeric_columns = [
131
+ "open", "high", "low", "close",
132
+ "volume", "volume_currency", "volume_quote"
133
+ ]
134
+
135
+ for col in numeric_columns:
136
+ df[col] = pd.to_numeric(df[col])
137
+
138
+ df["confirm"] = pd.to_numeric(df["confirm"])
139
+
140
+ df = (
141
+ df.sort_values("timestamp")
142
+ .drop_duplicates("timestamp")
143
+ .reset_index(drop=True)
144
+ )
145
+
146
+ return df
147
+
148
+
149
+ # =====================================
150
+ # TECHNICAL INDICATORS
151
+ # =====================================
152
+
153
+ def add_indicators(df):
154
+
155
+ df = df.copy()
156
+
157
+ df["return_pct"] = df["close"].pct_change() * 100
158
+
159
+ df["EMA20"] = df["close"].ewm(
160
+ span=20, adjust=False
161
+ ).mean()
162
+
163
+ df["EMA50"] = df["close"].ewm(
164
+ span=50, adjust=False
165
+ ).mean()
166
+
167
+ delta = df["close"].diff()
168
+
169
+ gain = delta.clip(lower=0).ewm(
170
+ alpha=1/14, adjust=False
171
+ ).mean()
172
+
173
+ loss = (-delta.clip(upper=0)).ewm(
174
+ alpha=1/14, adjust=False
175
+ ).mean()
176
+
177
+ rs = gain / loss.replace(0, float("nan"))
178
 
179
+ df["RSI"] = 100 - (100 / (1 + rs))
180
 
181
+ previous_close = df["close"].shift(1)
182
+
183
+ tr = pd.concat(
184
+ [
185
+ df["high"] - df["low"],
186
+ (df["high"] - previous_close).abs(),
187
+ (df["low"] - previous_close).abs()
188
+ ],
189
+ axis=1
190
+ ).max(axis=1)
191
+
192
+ df["ATR"] = tr.ewm(
193
+ alpha=1/14, adjust=False
194
+ ).mean()
195
+
196
+ df["volume_sma"] = df["volume"].rolling(20).mean()
197
+
198
+ return df
199
+
200
+
201
+ # =====================================
202
+ # GROQ AI ENGINE
203
+ # =====================================
204
+
205
+ def groq_analysis(df):
206
+
207
+ if not GROQ_API_KEY:
208
+ raise ValueError(
209
+ "GROQ_API_KEY bulunamadı. "
210
+ "Hugging Face Spaces Secrets bölümüne ekle."
211
  )
212
 
213
+ client = Groq(api_key=GROQ_API_KEY)
214
+
215
+ latest = df.tail(30).copy()
216
+
217
+ market_data = latest[
218
+ [
219
+ "timestamp",
220
+ "open",
221
+ "high",
222
+ "low",
223
+ "close",
224
+ "volume",
225
+ "return_pct",
226
+ "EMA20",
227
+ "EMA50",
228
+ "RSI",
229
+ "ATR"
230
  ]
231
+ ].round(4).to_string(index=False)
232
+
233
+ prompt = f"""
234
+ BTC-USDT piyasa analizini yap.
235
+
236
+ Aşağıdaki veriler OKX Public API üzerinden alınmıştır.
237
+
238
+ VERİLER:
239
+ {market_data}
240
+
241
+ ANALİZ:
242
+
243
+ 1. Genel trend.
244
+ 2. EMA20 ve EMA50.
245
+ 3. RSI momentum.
246
+ 4. ATR volatilitesi.
247
+ 5. Hacim davranışı.
248
+ 6. Destek bölgeleri.
249
+ 7. Direnç bölgeleri.
250
+ 8. Bullish senaryo.
251
+ 9. Bearish senaryo.
252
+ 10. Neutral senaryo.
253
+ 11. Risk analizi.
254
+
255
+ ÇIKTI:
256
+
257
+ YÖN: BULLISH / BEARISH / NEUTRAL
258
+ MODEL GÜVENİ: 0-100
259
+ TREND:
260
+ MOMENTUM:
261
+ DESTEK:
262
+ DİRENÇ:
263
+ YÜKSELİŞ SENARYOSU:
264
+ DÜŞÜŞ SENARYOSU:
265
+ RİSK:
266
+ NİHAİ ANALİZ:
267
+
268
+ ÖNEMLİ:
269
+ - Yalnızca verilen verileri kullan.
270
+ - Olmayan fiyatları uydurma.
271
+ - Güven puanının kalibre edilmiş olasılık olmadığını belirt.
272
+ - Kesin kazanç veya yön garantisi verme.
273
+ """
274
+
275
+ response = client.chat.completions.create(
276
+ model=GROQ_MODEL,
277
+ messages=[
278
+ {
279
+ "role": "system",
280
+ "content": (
281
+ "Sen profesyonel ve ihtiyatlı "
282
+ "bir kripto piyasa analiz AI sistemisin."
283
+ )
284
+ },
285
+ {
286
+ "role": "user",
287
+ "content": prompt
288
+ }
289
+ ],
290
+ temperature=0.2,
291
+ max_completion_tokens=1800
292
+ )
293
+
294
+ return response.choices[0].message.content
295
+
296
+
297
+ # =====================================
298
+ # MAIN APPLICATION
299
+ # =====================================
300
+
301
+ def run_system(days, timeframe, symbol):
302
 
303
+ try:
304
+
305
+ df = get_okx_data(
306
+ days,
307
+ timeframe,
308
+ symbol
309
+ )
310
 
311
+ df = add_indicators(df)
312
 
313
+ analysis = groq_analysis(df)
 
 
314
 
315
  temp = tempfile.NamedTemporaryFile(
316
  suffix=".csv",
317
+ prefix="OKX_BTC_",
318
  delete=False
319
  )
320
 
321
+ csv_path = temp.name
322
  temp.close()
323
 
324
+ df.to_csv(csv_path, index=False)
325
+
326
+ last = df.iloc[-1]
327
 
328
+ info = f"""
329
+ ## MARKET DATA
330
 
331
+ - Symbol: {symbol}
332
+ - Timeframe: {timeframe}
333
+ - Candle count: {len(df)}
334
+ - Last close: {last['close']:.2f}
335
+ - RSI: {last['RSI']:.2f}
336
+ - EMA20: {last['EMA20']:.2f}
337
+ - EMA50: {last['EMA50']:.2f}
338
+ - ATR: {last['ATR']:.2f}
339
  """
340
 
341
+ return (
342
+ info,
343
+ analysis,
344
+ csv_path,
345
+ df.tail(20)
346
+ )
347
 
348
  except Exception as e:
 
349
 
350
+ return (
351
+ f"ERROR: {str(e)}",
352
+ "",
353
+ None,
354
+ pd.DataFrame()
355
+ )
356
+
357
+
358
+ # =====================================
359
+ # GRADIO UI
360
+ # =====================================
361
 
362
+ with gr.Blocks(
363
+ title="OKX Groq BTC AI"
364
+ ) as demo:
365
 
366
  gr.Markdown("""
367
+ # BTC-USDT AI ANALYSIS ENGINE
368
 
369
+ ### OKX Public API + Groq Llama
370
 
371
+ Historical Data | Technical Analysis | AI Report | CSV
372
  """)
373
 
374
  with gr.Row():
375
+
376
  symbol = gr.Textbox(
377
  label="Trading Pair",
378
  value="BTC-USDT"
379
  )
380
 
381
  timeframe = gr.Dropdown(
382
+ choices=[
383
+ "1m", "3m", "5m", "15m",
384
+ "30m", "1H", "2H", "4H",
385
+ "6H", "12H", "1D"
386
+ ],
387
  value="1H",
388
  label="Timeframe"
389
  )
 
393
  maximum=90,
394
  value=30,
395
  step=1,
396
+ label="Historical Days"
397
  )
398
 
399
+ run = gr.Button(
400
+ "RUN GROQ BTC AI",
401
  variant="primary"
402
  )
403
 
404
+ market_info = gr.Markdown()
405
 
406
+ ai_output = gr.Markdown()
407
 
408
+ csv_output = gr.File(
409
+ label="Download BTC CSV"
 
410
  )
411
 
412
+ data_preview = gr.Dataframe(
413
+ label="Market Data Preview",
414
+ interactive=False
 
415
  )
416
 
417
+ run.click(
418
+ fn=run_system,
419
+ inputs=[
420
+ days,
421
+ timeframe,
422
+ symbol
423
+ ],
424
+ outputs=[
425
+ market_info,
426
+ ai_output,
427
+ csv_output,
428
+ data_preview
429
+ ]
430
+ )
431
 
 
 
 
432
 
433
+ demo.queue().launch(
434
+ server_name="0.0.0.0",
435
+ server_port=7860
436
+ )