heisbuba commited on
Commit
acbb457
·
verified ·
1 Parent(s): d5697c6

Create deep_diver_engine.py

Browse files
Files changed (1) hide show
  1. src/services/deep_diver_engine.py +97 -0
src/services/deep_diver_engine.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import time
3
+
4
+ # Reusing the exact Stealth Headers from spot_engine.py
5
+ STEALTH_HEADERS = {
6
+ "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",
7
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
8
+ "Accept-Language": "en-US,en;q=0.9",
9
+ "Accept-Encoding": "gzip, deflate, br",
10
+ "Connection": "keep-alive",
11
+ }
12
+
13
+ def calculate_deep_dive(ticker: str, user_keys: dict):
14
+ """
15
+ Quantitative Engine for Single-Ticker Analysis.
16
+ Fetches real-time depth and volume metrics from CoinGecko.
17
+ """
18
+ cg_key = user_keys.get("COINGECKO_API_KEY", "")
19
+
20
+ # Matching the API key logic from spot_engine.py
21
+ is_pro = "pro-api" in cg_key or (cg_key and len(cg_key) > 25)
22
+ base_url = "https://pro-api.coingecko.com/api/v3" if is_pro else "https://api.coingecko.com/api/v3"
23
+
24
+ headers = STEALTH_HEADERS.copy()
25
+ if cg_key:
26
+ # Use demo key header if not Pro
27
+ key_header = "x-cg-pro-api-key" if is_pro else "x-cg-demo-api-key"
28
+ headers[key_header] = cg_key
29
+
30
+ try:
31
+ # 1. Resolve Ticker to CoinGecko ID
32
+ search_url = f"{base_url}/search?query={ticker}"
33
+ search_res = requests.get(search_url, headers=headers, timeout=10).json()
34
+
35
+ if not search_res.get('coins'):
36
+ return {"status": "error", "message": f"Ticker '{ticker}' not found."}
37
+
38
+ coin_id = search_res['coins'][0]['id']
39
+
40
+ # 2. Fetch Deep Market Data with Depth
41
+ # We explicitly request 'tickers' to get the +/- 2% depth data
42
+ market_url = f"{base_url}/coins/{coin_id}?localization=false&tickers=true&market_data=true"
43
+ res = requests.get(market_url, headers=headers, timeout=15).json()
44
+
45
+ mkt = res.get('market_data', {})
46
+ tickers_list = res.get('tickers', [])
47
+
48
+ # --- QUANTITATIVE MATH ---
49
+
50
+ # VTPC: Volatility to Price Change (Abs % Vol Change / Abs % Price Change)
51
+ vol_change_pct = abs(mkt.get('total_volume_change_24h_percentage', 0))
52
+ price_change_pct = abs(mkt.get('price_change_percentage_24h', 0))
53
+ vtpc = round(vol_change_pct / price_change_pct, 2) if price_change_pct != 0 else 0
54
+
55
+ # VTAPC: Volume to Absorbed Price Change
56
+ # (Total Volume / Price Change %) = USD required for 1% move
57
+ total_vol = mkt.get('total_volume', {}).get('usd', 0)
58
+ vtapc = round(total_vol / price_change_pct, 0) if price_change_pct != 0 else 0
59
+
60
+ # VTMR: Volume to Market Cap Ratio
61
+ mcap = mkt.get('market_cap', {}).get('usd', 0)
62
+ vtmr = round(total_vol / mcap, 4) if mcap != 0 else 0
63
+
64
+ # --- REAL LIQUIDITY CALCULATION (LTMR) ---
65
+ # Summing the 2% depth (cost to move) across top 5 tickers
66
+ total_depth_2pct = 0
67
+ for t in tickers_list[:10]: # Look at top 10 liquid pairs
68
+ up = t.get('cost_to_move_up_usd', 0)
69
+ down = t.get('cost_to_move_down_usd', 0)
70
+ total_depth_2pct += (up + down)
71
+
72
+ # LTMR: Liquidity to Market Cap Ratio
73
+ ltmr = round(total_depth_2pct / mcap, 6) if mcap != 0 else 0
74
+
75
+ return {
76
+ "status": "success",
77
+ "ticker": ticker.upper(),
78
+ "vitals": {
79
+ "price": f"${mkt.get('current_price', {}).get('usd', 0):,.2f}",
80
+ "mcap": f"${mcap:,.0f}",
81
+ "vol24h": f"${total_vol:,.0f}"
82
+ },
83
+ "ratios": {
84
+ "vtpc": f"{vtpc}x",
85
+ "vtmr": vtmr,
86
+ "vtapc": f"${vtapc:,.0f}",
87
+ "ltmr": f"{ltmr:.5f}"
88
+ },
89
+ "velocity": {
90
+ "h24": f"{mkt.get('price_change_percentage_24h', 0):+.2f}%",
91
+ "w1": f"{mkt.get('price_change_percentage_7d', 0):+.2f}%",
92
+ "m1": f"{mkt.get('price_change_percentage_30d', 0):+.2f}%"
93
+ }
94
+ }
95
+
96
+ except Exception as e:
97
+ return {"status": "error", "message": f"Engine Error: {str(e)}"}