Spaces:
Sleeping
Sleeping
File size: 4,131 Bytes
c426a07 a38d5ba c6390ac a38d5ba c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 c6390ac c426a07 9dfe6eb c426a07 c6390ac c426a07 c6390ac c426a07 a38d5ba c426a07 c6390ac | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | import os
import sys
# Force UTF-8 stdout encoding for Windows terminal compatibility
sys.stdout.reconfigure(encoding='utf-8')
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import ccxt
from typing import Optional
from dotenv import load_dotenv
# Load .env variables (MODAL_TOKEN_ID, MODAL_TOKEN_SECRET)
load_dotenv()
# Import Modal cloud functions
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import modal
app = FastAPI(title="Binance Data Dashboard API")
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Binance client for symbol list only
try:
binance = ccxt.binance()
except Exception as e:
print(f"Warning: Could not init Binance client: {e}")
class DownloadRequest(BaseModel):
symbol: str
interval: str
data_type: str
start_date: str
end_date: str
threshold: Optional[float] = 1_000_000
agg_mode: Optional[str] = "Standard (Klines + Liq)"
datasetType: Optional[str] = None
@app.get("/api/symbols")
def get_symbols():
try:
markets = binance.load_markets()
symbols = sorted(list(markets.keys()))
return {"symbols": symbols}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/api/download")
def download_data(request: DownloadRequest):
print(f"\n{'='*60}")
print(f"[CLOUD] Download request:")
print(f" Symbol: {request.symbol}")
print(f" Interval: {request.interval}")
print(f" Data Type: {request.data_type}")
print(f" Start: {request.start_date}")
print(f" End: {request.end_date}")
print(f" Threshold: {request.threshold}")
print(f"{'='*60}")
try:
# Reference the deployed Modal app
modal_app = modal.App.lookup("binance-data-dashboard")
if request.data_type == 'Klines (OHLCV)':
print("[CLOUD] Calling fetch_klines_cloud...")
fn = modal.Function.from_name("binance-data-dashboard", "fetch_klines_cloud")
result = fn.remote(request.symbol, request.interval, request.start_date, request.end_date)
elif request.data_type == 'Liquidations':
print("[CLOUD] Calling fetch_liquidations_cloud...")
fn = modal.Function.from_name("binance-data-dashboard", "fetch_liquidations_cloud")
result = fn.remote(request.symbol, request.start_date, request.end_date)
elif request.data_type == 'AggTrades':
print("[CLOUD] Calling fetch_aggtrades_cloud...")
fn = modal.Function.from_name("binance-data-dashboard", "fetch_aggtrades_cloud")
result = fn.remote(request.symbol, request.start_date, request.end_date)
elif request.data_type == 'Dollar Bars (ML Ready)':
print(f"[CLOUD] Calling fetch_dollar_bars_cloud (threshold: {request.threshold})...")
fn = modal.Function.from_name("binance-data-dashboard", "fetch_dollar_bars_cloud")
result = fn.remote(request.symbol, request.start_date, request.end_date, request.threshold)
elif request.data_type == 'VPIN (Flow Toxicity)':
print(f"[CLOUD] Calling fetch_vpin_cloud (buckets: {request.threshold})...")
# Using threshold field temporarily to pass buckets_per_day or just hardcode
fn = modal.Function.from_name("binance-data-dashboard", "fetch_vpin_cloud")
# In UI we'll use threshold field for buckets per day
result = fn.remote(request.symbol, request.start_date, request.end_date, int(request.threshold))
else:
raise HTTPException(status_code=400, detail="Unknown data type.")
print(f"[CLOUD] Result received: success={result.get('success')}, rows={result.get('row_count', 0)}")
return result
except Exception as e:
print(f"KLAIDA: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
# Run with: uvicorn backend.api:app --reload
|