Spaces:
Running
Running
Update src/services/deep_diver_engine.py
Browse files
src/services/deep_diver_engine.py
CHANGED
|
@@ -9,13 +9,18 @@ STEALTH_HEADERS = {
|
|
| 9 |
}
|
| 10 |
|
| 11 |
def calculate_deep_dive(coin_id: str, user_keys: dict):
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
| 13 |
base_url = "https://api.coingecko.com/api/v3"
|
| 14 |
|
| 15 |
headers = STEALTH_HEADERS.copy()
|
| 16 |
-
|
|
|
|
| 17 |
if cg_key and cg_key != "CONFIG_REQUIRED_CG":
|
| 18 |
-
|
|
|
|
| 19 |
headers["x-cg-pro-api-key"] = cg_key
|
| 20 |
else:
|
| 21 |
headers["x-cg-demo-api-key"] = cg_key
|
|
@@ -24,20 +29,20 @@ def calculate_deep_dive(coin_id: str, user_keys: dict):
|
|
| 24 |
url = f"{base_url}/coins/{coin_id}?localization=false&tickers=true&market_data=true"
|
| 25 |
r = requests.get(url, headers=headers, timeout=15)
|
| 26 |
|
|
|
|
| 27 |
if r.status_code == 429:
|
| 28 |
-
return {"status": "error", "message": "Rate limit
|
| 29 |
-
|
|
|
|
| 30 |
if r.status_code != 200:
|
|
|
|
| 31 |
return {"status": "error", "message": f"API Error: {r.status_code}"}
|
| 32 |
|
| 33 |
res = r.json()
|
| 34 |
-
# Safety: Use ( ... or {}) to handle if 'market_data' is strictly None
|
| 35 |
mkt = res.get('market_data') or {}
|
| 36 |
|
| 37 |
-
# --- Core Vitals
|
| 38 |
-
# We use (mkt.get('x') or {}) to prevent AttributeError if the field is None
|
| 39 |
mcap = (mkt.get('market_cap') or {}).get('usd', 0) or 0
|
| 40 |
-
# Fallback to 1 to avoid division by zero later
|
| 41 |
mcap_calc = mcap if mcap > 0 else 1
|
| 42 |
|
| 43 |
vol = (mkt.get('total_volume') or {}).get('usd', 0) or 0
|
|
@@ -47,19 +52,15 @@ def calculate_deep_dive(coin_id: str, user_keys: dict):
|
|
| 47 |
v_ch = mkt.get('total_volume_change_24h_percentage', 0)
|
| 48 |
v_ch = v_ch if v_ch is not None else 0
|
| 49 |
|
| 50 |
-
# --- Ratio
|
| 51 |
vtpc_val = abs(v_ch / p_ch) if p_ch != 0 else 0
|
| 52 |
|
| 53 |
-
# --- LTMR Calculation ---
|
| 54 |
tickers = res.get('tickers') or []
|
| 55 |
-
# Calculate depth from top 10 pairs
|
| 56 |
depth = sum(
|
| 57 |
(t.get('cost_to_move_up_usd') or 0) + (t.get('cost_to_move_down_usd') or 0)
|
| 58 |
for t in tickers[:10]
|
| 59 |
)
|
| 60 |
ltmr = round(depth / mcap_calc, 6) if mcap > 0 else 0
|
| 61 |
-
|
| 62 |
-
# Current Price Logic
|
| 63 |
current_price = (mkt.get('current_price') or {}).get('usd', 0)
|
| 64 |
|
| 65 |
return {
|
|
|
|
| 9 |
}
|
| 10 |
|
| 11 |
def calculate_deep_dive(coin_id: str, user_keys: dict):
|
| 12 |
+
# 1. Sanitize Inputs (Crucial for preventing 400 Errors)
|
| 13 |
+
cg_key = str(user_keys.get("COINGECKO_API_KEY", "")).strip()
|
| 14 |
+
coin_id = str(coin_id).strip().lower()
|
| 15 |
+
|
| 16 |
base_url = "https://api.coingecko.com/api/v3"
|
| 17 |
|
| 18 |
headers = STEALTH_HEADERS.copy()
|
| 19 |
+
|
| 20 |
+
# 2. Header Logic (Safe Mode)
|
| 21 |
if cg_key and cg_key != "CONFIG_REQUIRED_CG":
|
| 22 |
+
# Pro keys are usually just alphanumeric, Demo keys start with CG-
|
| 23 |
+
if "pro-api" in base_url or (len(cg_key) > 10 and not cg_key.startswith("CG-")):
|
| 24 |
headers["x-cg-pro-api-key"] = cg_key
|
| 25 |
else:
|
| 26 |
headers["x-cg-demo-api-key"] = cg_key
|
|
|
|
| 29 |
url = f"{base_url}/coins/{coin_id}?localization=false&tickers=true&market_data=true"
|
| 30 |
r = requests.get(url, headers=headers, timeout=15)
|
| 31 |
|
| 32 |
+
# 3. Explicit Error Handling
|
| 33 |
if r.status_code == 429:
|
| 34 |
+
return {"status": "error", "message": "Rate limit. Wait 60s."}
|
| 35 |
+
if r.status_code == 404:
|
| 36 |
+
return {"status": "error", "message": f"Token '{coin_id}' not found."}
|
| 37 |
if r.status_code != 200:
|
| 38 |
+
print(f"DEBUG: Failed URL: {url} | Status: {r.status_code} | Key Used: {bool(cg_key)}")
|
| 39 |
return {"status": "error", "message": f"API Error: {r.status_code}"}
|
| 40 |
|
| 41 |
res = r.json()
|
|
|
|
| 42 |
mkt = res.get('market_data') or {}
|
| 43 |
|
| 44 |
+
# --- Core Vitals ---
|
|
|
|
| 45 |
mcap = (mkt.get('market_cap') or {}).get('usd', 0) or 0
|
|
|
|
| 46 |
mcap_calc = mcap if mcap > 0 else 1
|
| 47 |
|
| 48 |
vol = (mkt.get('total_volume') or {}).get('usd', 0) or 0
|
|
|
|
| 52 |
v_ch = mkt.get('total_volume_change_24h_percentage', 0)
|
| 53 |
v_ch = v_ch if v_ch is not None else 0
|
| 54 |
|
| 55 |
+
# --- Ratio Logic ---
|
| 56 |
vtpc_val = abs(v_ch / p_ch) if p_ch != 0 else 0
|
| 57 |
|
|
|
|
| 58 |
tickers = res.get('tickers') or []
|
|
|
|
| 59 |
depth = sum(
|
| 60 |
(t.get('cost_to_move_up_usd') or 0) + (t.get('cost_to_move_down_usd') or 0)
|
| 61 |
for t in tickers[:10]
|
| 62 |
)
|
| 63 |
ltmr = round(depth / mcap_calc, 6) if mcap > 0 else 0
|
|
|
|
|
|
|
| 64 |
current_price = (mkt.get('current_price') or {}).get('usd', 0)
|
| 65 |
|
| 66 |
return {
|