Spaces:
Running
Running
File size: 4,792 Bytes
acbb457 e3d6d2c 22b5453 d02d32c 22b5453 acbb457 22b5453 e3d6d2c acbb457 d02d32c e3d6d2c 22b5453 e3d6d2c 4151818 e3d6d2c 22b5453 e3d6d2c d02d32c 942233d d02d32c 942233d d02d32c 22b5453 d02d32c e3d6d2c 37551cd 22b5453 e3d6d2c acbb457 22b5453 d02d32c e3d6d2c d02d32c 226f4cb 22b5453 e3d6d2c d02d32c 22b5453 d02d32c 22b5453 4151818 e3d6d2c d02d32c 22b5453 e3d6d2c 4151818 22b5453 d02d32c e3d6d2c 93e57cf d02d32c e3d6d2c d02d32c e3d6d2c 22b5453 d02d32c e3d6d2c d02d32c e3d6d2c d02d32c e3d6d2c | 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 112 113 114 115 116 117 118 119 120 121 122 123 | import requests
import time
from decimal import Decimal, ROUND_HALF_UP
# --- Global Cache --- #
CACHE = {}
CACHE_DURATION = 120 # TTL set to 2 minutes
# Headers to mimic browser behavior and avoid basic scraping blocks
STEALTH_HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
"Connection": "keep-alive",
}
# --- Helper --- #
def format_compact(num):
"""Converts large numbers into human-readable strings (e.g., 1.5M, 2B)."""
if num is None or num == 0: return "0"
for unit in ['', 'K', 'M', 'B', 'T']:
if abs(num) < 1000.0:
return f"{num:,.2f}{unit}".replace(".00", "")
num /= 1000.0
return f"{num:,.2f}P"
def calculate_deep_dive(coin_id: str, user_keys: dict):
"""Fetches market data from CoinGecko, calculates ratios, and returns a structured payload."""
coin_id = coin_id.strip().lower()
# --- Cache Check --- #
now = time.time()
global CACHE
CACHE = {k: v for k, v in CACHE.items() if now < v['expires']}
if coin_id in CACHE:
print(f" ⚡ Serving {coin_id} from cache")
return CACHE[coin_id]['data']
# --- API Request Setup --- #
cg_key = str(user_keys.get("COINGECKO_API_KEY", "")).strip()
base_url = "https://api.coingecko.com/api/v3"
headers = STEALTH_HEADERS.copy()
# Handle both Demo and Pro API key formats
if cg_key and cg_key != "CONFIG_REQUIRED_CG":
headers["x-cg-demo-api-key" if cg_key.startswith("CG-") else "x-cg-pro-api-key"] = cg_key
try:
# Request only necessary fields to reduce payload size and latency
url = (f"{base_url}/coins/{coin_id}?"
"localization=false&"
"tickers=false&"
"market_data=true&"
"community_data=false&"
"developer_data=false&"
"sparkline=false&"
"price_change_percentage=1h")
r = requests.get(url, headers=headers, timeout=15)
if r.status_code == 429: return {"status": "error", "message": "Rate Limit Hit. Please wait."}
if r.status_code != 200: return {"status": "error", "message": f"API {r.status_code}"}
res = r.json()
mkt = res.get('market_data', {})
symbol = res.get('symbol', '').upper()
# --- Logic Extraction ---
mcap = mkt.get('market_cap', {}).get('usd', 0) or 0
vol = mkt.get('total_volume', {}).get('usd', 0) or 0
p_ch_24h = mkt.get('price_change_percentage_24h', 0) or 0
p_ch_1h = mkt.get('price_change_percentage_1h_in_currency', {}).get('usd', 0) or 0
d_vol = Decimal(str(vol))
d_mcap = Decimal(str(mcap))
# Volume-to-Market-Cap Ratio (VTMR)
vtmr_val = (d_vol / d_mcap).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) if d_mcap > 0 else 0
# Volume-to-Price-Change (VTPC) - Proxy for liquidity absorption
vtpc_val = vol / abs(p_ch_24h) if p_ch_24h != 0 else 0
current_price = mkt.get('current_price', {}).get('usd', 0)
# --- Link Construction --- #
links = {
"cg": f"https://www.coingecko.com/en/coins/{coin_id}",
"tv": f"https://www.tradingview.com/chart/?symbol={symbol}USDT"
}
# --- Payload Construction --- #
data_payload = {
"status": "success",
"vitals": {
"name": res.get('name', 'Unknown'),
"symbol": symbol,
"price": f"${current_price:,.8f}" if current_price < 1 else f"${current_price:,.2f}",
"mcap": f"${format_compact(mcap)}",
"vol24h": f"${format_compact(vol)}"
},
"ratios": {
"vtmr": f"{vtmr_val}x",
"vtpc": f"${format_compact(vtpc_val)}"
},
"velocity": {
"h1": f"{p_ch_1h:+.2f}%",
"h24": f"{p_ch_24h:+.2f}%",
"d7": f"{(mkt.get('price_change_percentage_7d') or 0):+.2f}%",
"m1": f"{(mkt.get('price_change_percentage_30d') or 0):+.2f}%",
"y1": f"{(mkt.get('price_change_percentage_1y') or 0):+.2f}%"
},
"supply": {
"total": format_compact(mkt.get('total_supply', 0))
},
"links": links
}
# --- Save to Cache --- #
CACHE[coin_id] = {'data': data_payload, 'expires': now + CACHE_DURATION}
return data_payload
except Exception as e:
return {"status": "error", "message": str(e)} |