roowoo commited on
Commit
e74fc4b
·
verified ·
1 Parent(s): bbce23f

Title: CryptoPulse Navigator — Intelligent CoinGlass Dashboard

Browse files

Instruction:

Build and host a full-stack crypto intelligence dashboard that scrapes and visualizes live market data from https://www.coinglass.com/
.
Use the latest market overview page to extract all real-time data available (funding rates, long/short ratio, liquidation volume, open interest, top gainers/losers, BTC/ETH metrics, etc.).

The goal is to automatically scrape, calculate, store, and display actionable indicators in a dynamic dashboard called CryptoPulse Navigator.

Follow these build requirements and logic exactly:

1. Data Collection

Scrape target:
https://www.coinglass.com/ → extract all tables and cards containing:

BTC/ETH prices, dominance, and funding rates

Global long vs short ratio

Open interest (24h change %)

Liquidation data (long vs short)

Exchange funding rate averages (Binance, OKX, Bybit)

Top gainers/losers (symbols and % change)

Stablecoin dominance

Fear & Greed Index if visible

Scraping method:

Use requests + BeautifulSoup4 (or Playwright if JS rendering needed).

Parse numerical values into floats and timestamps into UTC format.

Store all data in a structured JSON dictionary:

{
"timestamp": "...",
"btc": {...},
"eth": {...},
"funding_rates": {...},
"open_interest": {...},
"liquidations": {...},
"market_sentiment": {...},
"top_gainers": [...],
"top_losers": [...]
}

2. Data Processing and Calculations

Compute and cache the following synthetic indicators:

Metric Formula
Volatility Index (VOLX) Standard deviation of BTC hourly prices (σ × 1000)
Momentum Index (MOMX) % change of BTC price over last 24h
Funding Bias Score (FBS) Mean(funding_rate × 100)
Leverage Pressure Index (LPI) (OI change % + liquidation volume %) ÷ 2
PHI Score (Position Health Index) 0.4×VOLX + 0.3×MOMX + 0.2×FBS + 0.1×LPI
Phase Classification Compression (<30), Recovery (30-50), Expansion (50-70), Exhaustion (>70)

Cache results every 5 minutes in /data/cache.json.

3. Data Storage

Use a simple JSON file (data/cache.json) for latest snapshot.

Store 24h historical data in /data/history.json (append each scrape).

Auto-rotate (keep last 288 entries, 5-minute resolution).

4. Dashboard Frontend

Technology:
TailwindCSS + Chart.js + Axios (fetch from Flask endpoints).

Components:

Global Summary Card – PHI Score, Market Phase, Risk Regime.

Volatility & Momentum Bars – visualized as progress bars.

Funding & OI Overview – sparkline charts per exchange.

Long/Short Ratio Donut Chart.

Top Gainers / Losers Table.

BTC/ETH Detail Cards – price, 24h %, funding, OI, liquidations.

Update Timer + “Last Sync” timestamp.

5. Flask Backend

/api/scrape → triggers data scrape from CoinGlass.

/api/data → returns latest cached JSON.

/api/history → returns historical array for charts.

Automatically refresh scrape every 5 minutes in background thread.

6. Data Flow Logic

scraper.py runs → scrapes & computes PHI metrics.

Data stored in /data/cache.json.

Dashboard (index.html) fetches from /api/data.

If data stale (>6 min), trigger /api/scrape automatically.

Render updated metrics instantly.

7. Behavior Rules

If CoinGlass blocks direct requests (Cloudflare), use Playwright headless Chromium with a rotating User-Agent.

Always retry up to 3 times before failing gracefully.

Display “Live / Delayed / Offline” status on dashboard header.

Log every update in /logs/updates.log.

8. Output Expectation

Once deployed on Hugging Face:

Visit your Space (e.g., https://<your-space>.hf.space)

Dashboard auto-loads global metrics.

Refresh every 5 minutes.

Shows PHI Score, Market Phase, Long/Short Ratio, and dynamic price updates.

Console confirms:

Scrape complete ✓
Data cached ✓
PHI Score computed: 63 (Expansion)


End

Files changed (2) hide show
  1. README.md +8 -5
  2. index.html +827 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Cryptopulse Navigator
3
- emoji: 💻
4
- colorFrom: green
5
- colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: CryptoPulse Navigator 🚀
3
+ colorFrom: purple
4
+ colorTo: red
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
index.html CHANGED
@@ -1,19 +1,828 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>CryptoPulse Navigator - Intelligent CoinGlass Dashboard</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
12
+ <script src="https://unpkg.com/feather-icons"></script>
13
+ <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script>
14
+ <script>
15
+ tailwind.config = {
16
+ theme: {
17
+ extend: {
18
+ colors: {
19
+ primary: '#6366f1',
20
+ secondary: '#10b981',
21
+ dark: '#1e293b',
22
+ darker: '#0f172a'
23
+ }
24
+ }
25
+ }
26
+ }
27
+ </script>
28
+ <style>
29
+ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
30
+ body {
31
+ font-family: 'Space Grotesk', sans-serif;
32
+ }
33
+ .glass-card {
34
+ backdrop-filter: blur(16px) saturate(180%);
35
+ -webkit-backdrop-filter: blur(16px) saturate(180%);
36
+ background-color: rgba(30, 41, 59, 0.75);
37
+ border: 1px solid rgba(255, 255, 255, 0.125);
38
+ }
39
+ .phase-badge {
40
+ transition: all 0.3s ease;
41
+ }
42
+ .phase-badge:hover {
43
+ transform: scale(1.05);
44
+ }
45
+ </style>
46
+ </head>
47
+ <body class="bg-darker text-white min-h-screen">
48
+ <div id="vanta-bg" class="fixed inset-0 -z-10"></div>
49
+
50
+ <div class="container mx-auto px-4 py-8">
51
+ <!-- Header -->
52
+ <header class="flex justify-between items-center mb-8">
53
+ <div>
54
+ <h1 class="text-3xl font-bold flex items-center">
55
+ <i data-feather="activity" class="mr-2 text-primary"></i>
56
+ CryptoPulse <span class="text-primary">Navigator</span>
57
+ </h1>
58
+ <p class="text-gray-400">Intelligent CoinGlass Dashboard</p>
59
+ </div>
60
+ <div class="flex items-center space-x-4">
61
+ <div id="status-badge" class="px-3 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 flex items-center">
62
+ <span class="w-2 h-2 rounded-full bg-green-500 mr-2"></span>
63
+ <span>Live</span>
64
+ </div>
65
+ <div id="last-updated" class="text-gray-400 text-sm">
66
+ <i data-feather="clock" class="w-4 h-4 inline mr-1"></i>
67
+ <span>Updating...</span>
68
+ </div>
69
+ <button id="refresh-btn" class="p-2 rounded-full hover:bg-gray-800 transition">
70
+ <i data-feather="refresh-cw" class="w-5 h-5"></i>
71
+ </button>
72
+ </div>
73
+ </header>
74
+
75
+ <!-- PHI Score and Market Phase -->
76
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
77
+ <!-- PHI Score Card -->
78
+ <div class="glass-card p-6 rounded-xl col-span-1 lg:col-span-2">
79
+ <div class="flex justify-between items-start mb-4">
80
+ <div>
81
+ <h2 class="text-xl font-semibold">Market Health Index</h2>
82
+ <p class="text-gray-400 text-sm">PHI Score (Position Health Index)</p>
83
+ </div>
84
+ <div id="phase-badge" class="px-3 py-1 rounded-full bg-opacity-20 bg-secondary text-secondary phase-badge">
85
+ Loading...
86
+ </div>
87
+ </div>
88
+ <div class="flex items-center">
89
+ <div class="w-32 h-32 flex items-center justify-center relative">
90
+ <canvas id="phi-gauge" width="160" height="160"></canvas>
91
+ <div class="absolute text-center">
92
+ <div id="phi-score" class="text-4xl font-bold">--</div>
93
+ <div class="text-xs text-gray-400">PHI Score</div>
94
+ </div>
95
+ </div>
96
+ <div class="ml-6 flex-1">
97
+ <div class="mb-4">
98
+ <div class="flex justify-between text-sm mb-1">
99
+ <span>Volatility (VOLX)</span>
100
+ <span id="volx-value" class="font-medium">--</span>
101
+ </div>
102
+ <div class="w-full bg-gray-700 rounded-full h-2">
103
+ <div id="volx-bar" class="bg-yellow-500 h-2 rounded-full" style="width: 0%"></div>
104
+ </div>
105
+ </div>
106
+ <div class="mb-4">
107
+ <div class="flex justify-between text-sm mb-1">
108
+ <span>Momentum (MOMX)</span>
109
+ <span id="momx-value" class="font-medium">--</span>
110
+ </div>
111
+ <div class="w-full bg-gray-700 rounded-full h-2">
112
+ <div id="momx-bar" class="bg-blue-500 h-2 rounded-full" style="width: 0%"></div>
113
+ </div>
114
+ </div>
115
+ <div class="mb-4">
116
+ <div class="flex justify-between text-sm mb-1">
117
+ <span>Funding Bias (FBS)</span>
118
+ <span id="fbs-value" class="font-medium">--</span>
119
+ </div>
120
+ <div class="w-full bg-gray-700 rounded-full h-2">
121
+ <div id="fbs-bar" class="bg-purple-500 h-2 rounded-full" style="width: 0%"></div>
122
+ </div>
123
+ </div>
124
+ <div>
125
+ <div class="flex justify-between text-sm mb-1">
126
+ <span>Leverage (LPI)</span>
127
+ <span id="lpi-value" class="font-medium">--</span>
128
+ </div>
129
+ <div class="w-full bg-gray-700 rounded-full h-2">
130
+ <div id="lpi-bar" class="bg-red-500 h-2 rounded-full" style="width: 0%"></div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+
137
+ <!-- Market Overview -->
138
+ <div class="glass-card p-6 rounded-xl">
139
+ <h2 class="text-xl font-semibold mb-4">Market Overview</h2>
140
+ <div class="space-y-4">
141
+ <div>
142
+ <div class="flex justify-between text-sm mb-1">
143
+ <span>Long/Short Ratio</span>
144
+ <span id="ls-ratio-value" class="font-medium">--</span>
145
+ </div>
146
+ <div class="w-full h-3 bg-gray-700 rounded-full overflow-hidden">
147
+ <div class="h-full flex">
148
+ <div id="long-bar" class="bg-green-500" style="width: 50%"></div>
149
+ <div id="short-bar" class="bg-red-500" style="width: 50%"></div>
150
+ </div>
151
+ </div>
152
+ </div>
153
+ <div>
154
+ <div class="text-sm mb-1">Fear & Greed Index</div>
155
+ <div class="w-full bg-gray-700 rounded-full h-2">
156
+ <div id="fear-greed-bar" class="bg-gradient-to-r from-red-500 via-yellow-500 to-green-500 h-2 rounded-full" style="width: 50%"></div>
157
+ </div>
158
+ <div id="fear-greed-value" class="text-right text-xs mt-1">--</div>
159
+ </div>
160
+ <div class="pt-2">
161
+ <div class="text-sm mb-1">Market Phase</div>
162
+ <div id="phase-description" class="text-sm text-gray-300">
163
+ Loading market phase description...
164
+ </div>
165
+ </div>
166
+ <div class="pt-2">
167
+ <div class="text-sm mb-1">Risk Level</div>
168
+ <div id="risk-level" class="text-sm font-medium">
169
+ <span class="px-2 py-1 rounded bg-opacity-20 bg-gray-500">Calculating...</span>
170
+ </div>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </div>
175
+
176
+ <!-- BTC/ETH Cards -->
177
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
178
+ <!-- BTC Card -->
179
+ <div class="glass-card p-6 rounded-xl">
180
+ <div class="flex justify-between items-start mb-4">
181
+ <div class="flex items-center">
182
+ <img src="https://cryptologos.cc/logos/bitcoin-btc-logo.png" alt="BTC" class="w-8 h-8 mr-3">
183
+ <div>
184
+ <h2 class="text-xl font-semibold">Bitcoin</h2>
185
+ <div class="flex items-center">
186
+ <span id="btc-price" class="text-2xl font-bold">--</span>
187
+ <span id="btc-change" class="ml-2 px-2 py-1 rounded text-xs"></span>
188
+ </div>
189
+ </div>
190
+ </div>
191
+ <div class="text-xs text-gray-400">
192
+ Dominance: <span id="btc-dominance" class="font-medium">--%</span>
193
+ </div>
194
+ </div>
195
+ <div class="grid grid-cols-3 gap-4">
196
+ <div>
197
+ <div class="text-xs text-gray-400 mb-1">Funding Rate</div>
198
+ <div id="btc-funding" class="text-lg font-medium">--%</div>
199
+ </div>
200
+ <div>
201
+ <div class="text-xs text-gray-400 mb-1">Open Interest</div>
202
+ <div id="btc-oi" class="text-lg font-medium">--</div>
203
+ </div>
204
+ <div>
205
+ <div class="text-xs text-gray-400 mb-1">Liquidation</div>
206
+ <div class="flex items-center">
207
+ <span id="btc-liquidations" class="text-lg font-medium">--</span>
208
+ <span id="btc-liq-change" class="ml-1 text-xs"></span>
209
+ </div>
210
+ </div>
211
+ </div>
212
+ <div class="mt-4 h-20">
213
+ <canvas id="btc-chart"></canvas>
214
+ </div>
215
+ </div>
216
+
217
+ <!-- ETH Card -->
218
+ <div class="glass-card p-6 rounded-xl">
219
+ <div class="flex justify-between items-start mb-4">
220
+ <div class="flex items-center">
221
+ <img src="https://cryptologos.cc/logos/ethereum-eth-logo.png" alt="ETH" class="w-8 h-8 mr-3">
222
+ <div>
223
+ <h2 class="text-xl font-semibold">Ethereum</h2>
224
+ <div class="flex items-center">
225
+ <span id="eth-price" class="text-2xl font-bold">--</span>
226
+ <span id="eth-change" class="ml-2 px-2 py-1 rounded text-xs"></span>
227
+ </div>
228
+ </div>
229
+ </div>
230
+ <div class="text-xs text-gray-400">
231
+ Dominance: <span id="eth-dominance" class="font-medium">--%</span>
232
+ </div>
233
+ </div>
234
+ <div class="grid grid-cols-3 gap-4">
235
+ <div>
236
+ <div class="text-xs text-gray-400 mb-1">Funding Rate</div>
237
+ <div id="eth-funding" class="text-lg font-medium">--%</div>
238
+ </div>
239
+ <div>
240
+ <div class="text-xs text-gray-400 mb-1">Open Interest</div>
241
+ <div id="eth-oi" class="text-lg font-medium">--</div>
242
+ </div>
243
+ <div>
244
+ <div class="text-xs text-gray-400 mb-1">Liquidation</div>
245
+ <div class="flex items-center">
246
+ <span id="eth-liquidations" class="text-lg font-medium">--</span>
247
+ <span id="eth-liq-change" class="ml-1 text-xs"></span>
248
+ </div>
249
+ </div>
250
+ </div>
251
+ <div class="mt-4 h-20">
252
+ <canvas id="eth-chart"></canvas>
253
+ </div>
254
+ </div>
255
+ </div>
256
+
257
+ <!-- Gainers & Losers -->
258
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
259
+ <!-- Top Gainers -->
260
+ <div class="glass-card p-6 rounded-xl">
261
+ <div class="flex justify-between items-center mb-4">
262
+ <h2 class="text-xl font-semibold">Top Gainers</h2>
263
+ <span class="px-2 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 text-xs">24h</span>
264
+ </div>
265
+ <div id="gainers-list" class="space-y-3">
266
+ <div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
267
+ <div class="flex items-center">
268
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
269
+ <div class="w-20 h-4 bg-gray-700 rounded"></div>
270
+ </div>
271
+ <div class="w-16 h-4 bg-gray-700 rounded"></div>
272
+ </div>
273
+ <div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
274
+ <div class="flex items-center">
275
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
276
+ <div class="w-20 h-4 bg-gray-700 rounded"></div>
277
+ </div>
278
+ <div class="w-16 h-4 bg-gray-700 rounded"></div>
279
+ </div>
280
+ <div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
281
+ <div class="flex items-center">
282
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
283
+ <div class="w-20 h-4 bg-gray-700 rounded"></div>
284
+ </div>
285
+ <div class="w-16 h-4 bg-gray-700 rounded"></div>
286
+ </div>
287
+ </div>
288
+ </div>
289
+
290
+ <!-- Top Losers -->
291
+ <div class="glass-card p-6 rounded-xl">
292
+ <div class="flex justify-between items-center mb-4">
293
+ <h2 class="text-xl font-semibold">Top Losers</h2>
294
+ <span class="px-2 py-1 rounded-full bg-opacity-20 bg-red-500 text-red-300 text-xs">24h</span>
295
+ </div>
296
+ <div id="losers-list" class="space-y-3">
297
+ <div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
298
+ <div class="flex items-center">
299
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
300
+ <div class="w-20 h-4 bg-gray-700 rounded"></div>
301
+ </div>
302
+ <div class="w-16 h-4 bg-gray-700 rounded"></div>
303
+ </div>
304
+ <div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
305
+ <div class="flex items-center">
306
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
307
+ <div class="w-20 h-4 bg-gray-700 rounded"></div>
308
+ </div>
309
+ <div class="w-16 h-4 bg-gray-700 rounded"></div>
310
+ </div>
311
+ <div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
312
+ <div class="flex items-center">
313
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
314
+ <div class="w-20 h-4 bg-gray-700 rounded"></div>
315
+ </div>
316
+ <div class="w-16 h-4 bg-gray-700 rounded"></div>
317
+ </div>
318
+ </div>
319
+ </div>
320
+ </div>
321
+
322
+ <!-- Funding Rates & Open Interest -->
323
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
324
+ <!-- Funding Rates -->
325
+ <div class="glass-card p-6 rounded-xl">
326
+ <h2 class="text-xl font-semibold mb-4">Exchange Funding Rates</h2>
327
+ <div class="h-64">
328
+ <canvas id="funding-chart"></canvas>
329
+ </div>
330
+ </div>
331
+
332
+ <!-- Open Interest -->
333
+ <div class="glass-card p-6 rounded-xl">
334
+ <h2 class="text-xl font-semibold mb-4">Open Interest</h2>
335
+ <div class="h-64">
336
+ <canvas id="oi-chart"></canvas>
337
+ </div>
338
+ </div>
339
+ </div>
340
+
341
+ <!-- Liquidation Heatmap -->
342
+ <div class="glass-card p-6 rounded-xl mb-8">
343
+ <h2 class="text-xl font-semibold mb-4">Liquidation Heatmap</h2>
344
+ <div class="h-80">
345
+ <canvas id="liquidation-chart"></canvas>
346
+ </div>
347
+ </div>
348
+
349
+ <!-- Footer -->
350
+ <footer class="text-center text-gray-500 text-sm py-6">
351
+ <div class="flex justify-center space-x-4 mb-2">
352
+ <a href="#" class="hover:text-primary transition"><i data-feather="github"></i></a>
353
+ <a href="#" class="hover:text-primary transition"><i data-feather="twitter"></i></a>
354
+ <a href="#" class="hover:text-primary transition"><i data-feather="discord"></i></a>
355
+ </div>
356
+ <p>CryptoPulse Navigator - Real-time Crypto Market Intelligence</p>
357
+ <p class="text-xs mt-1">Data sourced from CoinGlass | Updates every 5 minutes</p>
358
+ </footer>
359
+ </div>
360
+
361
+ <script>
362
+ // Initialize Vanta.js background
363
+ VANTA.NET({
364
+ el: "#vanta-bg",
365
+ mouseControls: true,
366
+ touchControls: true,
367
+ gyroControls: false,
368
+ minHeight: 200.00,
369
+ minWidth: 200.00,
370
+ scale: 1.00,
371
+ scaleMobile: 1.00,
372
+ color: 0x6366f1,
373
+ backgroundColor: 0x0f172a,
374
+ points: 12.00,
375
+ maxDistance: 22.00,
376
+ spacing: 18.00
377
+ });
378
+
379
+ // Initialize charts
380
+ const phiCtx = document.getElementById('phi-gauge').getContext('2d');
381
+ const phiGauge = new Chart(phiCtx, {
382
+ type: 'doughnut',
383
+ data: {
384
+ datasets: [{
385
+ data: [0, 100],
386
+ backgroundColor: ['#6366f1', 'rgba(30, 41, 59, 0.5)'],
387
+ borderWidth: 0
388
+ }]
389
+ },
390
+ options: {
391
+ cutout: '85%',
392
+ rotation: -90,
393
+ circumference: 180,
394
+ responsive: false,
395
+ plugins: {
396
+ legend: { display: false },
397
+ tooltip: { enabled: false }
398
+ }
399
+ }
400
+ });
401
+
402
+ // Initialize other charts
403
+ const btcChart = new Chart(document.getElementById('btc-chart'), {
404
+ type: 'line',
405
+ data: {
406
+ labels: Array(24).fill(''),
407
+ datasets: [{
408
+ data: Array(24).fill(0),
409
+ borderColor: '#f59e0b',
410
+ borderWidth: 2,
411
+ tension: 0.3,
412
+ fill: true,
413
+ backgroundColor: 'rgba(245, 158, 11, 0.1)',
414
+ pointRadius: 0
415
+ }]
416
+ },
417
+ options: {
418
+ responsive: true,
419
+ maintainAspectRatio: false,
420
+ plugins: { legend: { display: false } },
421
+ scales: {
422
+ x: { display: false },
423
+ y: { display: false }
424
+ }
425
+ }
426
+ });
427
+
428
+ const ethChart = new Chart(document.getElementById('eth-chart'), {
429
+ type: 'line',
430
+ data: {
431
+ labels: Array(24).fill(''),
432
+ datasets: [{
433
+ data: Array(24).fill(0),
434
+ borderColor: '#8b5cf6',
435
+ borderWidth: 2,
436
+ tension: 0.3,
437
+ fill: true,
438
+ backgroundColor: 'rgba(139, 92, 246, 0.1)',
439
+ pointRadius: 0
440
+ }]
441
+ },
442
+ options: {
443
+ responsive: true,
444
+ maintainAspectRatio: false,
445
+ plugins: { legend: { display: false } },
446
+ scales: {
447
+ x: { display: false },
448
+ y: { display: false }
449
+ }
450
+ }
451
+ });
452
+
453
+ const fundingChart = new Chart(document.getElementById('funding-chart'), {
454
+ type: 'bar',
455
+ data: {
456
+ labels: ['Binance', 'OKX', 'Bybit', 'Deribit', 'Bitget'],
457
+ datasets: [{
458
+ label: 'Funding Rate',
459
+ data: [0.01, 0.005, 0.007, -0.002, 0.003],
460
+ backgroundColor: [
461
+ 'rgba(99, 102, 241, 0.7)',
462
+ 'rgba(99, 102, 241, 0.7)',
463
+ 'rgba(99, 102, 241, 0.7)',
464
+ 'rgba(99, 102, 241, 0.7)',
465
+ 'rgba(99, 102, 241, 0.7)'
466
+ ],
467
+ borderColor: [
468
+ 'rgba(99, 102, 241, 1)',
469
+ 'rgba(99, 102, 241, 1)',
470
+ 'rgba(99, 102, 241, 1)',
471
+ 'rgba(99, 102, 241, 1)',
472
+ 'rgba(99, 102, 241, 1)'
473
+ ],
474
+ borderWidth: 1
475
+ }]
476
+ },
477
+ options: {
478
+ responsive: true,
479
+ maintainAspectRatio: false,
480
+ plugins: {
481
+ legend: { display: false },
482
+ tooltip: {
483
+ callbacks: {
484
+ label: function(context) {
485
+ return (context.raw * 100).toFixed(4) + '%';
486
+ }
487
+ }
488
+ }
489
+ },
490
+ scales: {
491
+ y: {
492
+ beginAtZero: true,
493
+ ticks: {
494
+ callback: function(value) {
495
+ return (value * 100).toFixed(2) + '%';
496
+ }
497
+ }
498
+ }
499
+ }
500
+ }
501
+ });
502
+
503
+ const oiChart = new Chart(document.getElementById('oi-chart'), {
504
+ type: 'line',
505
+ data: {
506
+ labels: ['6h ago', '5h ago', '4h ago', '3h ago', '2h ago', '1h ago', 'Now'],
507
+ datasets: [
508
+ {
509
+ label: 'BTC',
510
+ data: [12000, 12500, 12300, 12800, 12700, 13000, 13200],
511
+ borderColor: '#f59e0b',
512
+ backgroundColor: 'rgba(245, 158, 11, 0.1)',
513
+ tension: 0.3,
514
+ fill: true
515
+ },
516
+ {
517
+ label: 'ETH',
518
+ data: [8000, 8200, 8100, 8300, 8250, 8400, 8500],
519
+ borderColor: '#8b5cf6',
520
+ backgroundColor: 'rgba(139, 92, 246, 0.1)',
521
+ tension: 0.3,
522
+ fill: true
523
+ }
524
+ ]
525
+ },
526
+ options: {
527
+ responsive: true,
528
+ maintainAspectRatio: false,
529
+ plugins: {
530
+ tooltip: {
531
+ callbacks: {
532
+ label: function(context) {
533
+ return context.dataset.label + ': $' + context.raw.toLocaleString();
534
+ }
535
+ }
536
+ }
537
+ },
538
+ scales: {
539
+ y: {
540
+ ticks: {
541
+ callback: function(value) {
542
+ return '$' + (value / 1000) + 'B';
543
+ }
544
+ }
545
+ }
546
+ }
547
+ }
548
+ });
549
+
550
+ const liquidationChart = new Chart(document.getElementById('liquidation-chart'), {
551
+ type: 'bar',
552
+ data: {
553
+ labels: ['BTC', 'ETH', 'SOL', 'XRP', 'ADA', 'DOT', 'DOGE', 'MATIC'],
554
+ datasets: [
555
+ {
556
+ label: 'Long',
557
+ data: [12000000, 8500000, 3200000, 1800000, 1500000, 1200000, 900000, 800000],
558
+ backgroundColor: 'rgba(16, 185, 129, 0.7)',
559
+ borderColor: 'rgba(16, 185, 129, 1)',
560
+ borderWidth: 1
561
+ },
562
+ {
563
+ label: 'Short',
564
+ data: [9500000, 7200000, 2800000, 1500000, 1200000, 900000, 700000, 600000],
565
+ backgroundColor: 'rgba(239, 68, 68, 0.7)',
566
+ borderColor: 'rgba(239, 68, 68, 1)',
567
+ borderWidth: 1
568
+ }
569
+ ]
570
+ },
571
+ options: {
572
+ responsive: true,
573
+ maintainAspectRatio: false,
574
+ plugins: {
575
+ tooltip: {
576
+ callbacks: {
577
+ label: function(context) {
578
+ return context.dataset.label + ': $' + (context.raw / 1000000).toFixed(2) + 'M';
579
+ }
580
+ }
581
+ }
582
+ },
583
+ scales: {
584
+ x: { stacked: true },
585
+ y: {
586
+ stacked: true,
587
+ ticks: {
588
+ callback: function(value) {
589
+ return '$' + (value / 1000000) + 'M';
590
+ }
591
+ }
592
+ }
593
+ }
594
+ }
595
+ });
596
+
597
+ // Fetch data from API
598
+ async function fetchData() {
599
+ try {
600
+ document.getElementById('status-badge').className = 'px-3 py-1 rounded-full bg-opacity-20 bg-yellow-500 text-yellow-300 flex items-center';
601
+ document.querySelector('#status-badge span:last-child').textContent = 'Updating';
602
+
603
+ const response = await axios.get('/api/data');
604
+ const data = response.data;
605
+
606
+ updateDashboard(data);
607
+
608
+ document.getElementById('status-badge').className = 'px-3 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 flex items-center';
609
+ document.querySelector('#status-badge span:last-child').textContent = 'Live';
610
+ document.getElementById('last-updated').innerHTML = `<i data-feather="clock" class="w-4 h-4 inline mr-1"></i> ${new Date().toLocaleTimeString()}`;
611
+ } catch (error) {
612
+ console.error('Error fetching data:', error);
613
+ document.getElementById('status-badge').className = 'px-3 py-1 rounded-full bg-opacity-20 bg-red-500 text-red-300 flex items-center';
614
+ document.querySelector('#status-badge span:last-child').textContent = 'Offline';
615
+ }
616
+ }
617
+
618
+ // Update dashboard with data
619
+ function updateDashboard(data) {
620
+ // PHI Score and Metrics
621
+ const phiScore = data.phi_score || 50;
622
+ document.getElementById('phi-score').textContent = phiScore.toFixed(1);
623
+
624
+ // Update gauge chart
625
+ phiGauge.data.datasets[0].data = [phiScore, 100 - phiScore];
626
+ phiGauge.update();
627
+
628
+ // Update metric bars
629
+ document.getElementById('volx-value').textContent = data.volx ? data.volx.toFixed(1) : '--';
630
+ document.getElementById('momx-value').textContent = data.momx ? (data.momx * 100).toFixed(2) + '%' : '--';
631
+ document.getElementById('fbs-value').textContent = data.fbs ? (data.fbs * 100).toFixed(4) + '%' : '--';
632
+ document.getElementById('lpi-value').textContent = data.lpi ? data.lpi.toFixed(1) : '--';
633
+
634
+ document.getElementById('volx-bar').style.width = `${data.volx || 0}%`;
635
+ document.getElementById('momx-bar').style.width = `${(data.momx || 0) * 100}%`;
636
+ document.getElementById('fbs-bar').style.width = `${(data.fbs || 0) * 100}%`;
637
+ document.getElementById('lpi-bar').style.width = `${data.lpi || 0}%`;
638
+
639
+ // Update market phase
640
+ let phase = 'Neutral';
641
+ let phaseColor = 'gray';
642
+
643
+ if (phiScore < 30) {
644
+ phase = 'Compression';
645
+ phaseColor = 'purple';
646
+ } else if (phiScore < 50) {
647
+ phase = 'Recovery';
648
+ phaseColor = 'blue';
649
+ } else if (phiScore < 70) {
650
+ phase = 'Expansion';
651
+ phaseColor = 'green';
652
+ } else {
653
+ phase = 'Exhaustion';
654
+ phaseColor = 'red';
655
+ }
656
+
657
+ const phaseBadge = document.getElementById('phase-badge');
658
+ phaseBadge.textContent = phase;
659
+ phaseBadge.className = `px-3 py-1 rounded-full bg-opacity-20 bg-${phaseColor}-500 text-${phaseColor}-300 phase-badge`;
660
+
661
+ // Update phase description
662
+ const descriptions = {
663
+ 'Compression': 'Market is in a compression phase with low volatility. Traders are cautious, awaiting a breakout.',
664
+ 'Recovery': 'Market is recovering from recent moves. Volatility is increasing as traders reposition.',
665
+ 'Expansion': 'Market is in expansion with strong momentum. Trending conditions likely to continue.',
666
+ 'Exhaustion': 'Market shows signs of exhaustion after strong moves. Potential reversal or consolidation ahead.',
667
+ 'Neutral': 'Market is in neutral territory without clear direction. Watch for breakout signals.'
668
+ };
669
+
670
+ document.getElementById('phase-description').textContent = descriptions[phase] || descriptions['Neutral'];
671
+
672
+ // Update risk level
673
+ let riskLevel = 'Medium';
674
+ let riskColor = 'yellow';
675
+
676
+ if (phiScore < 20 || phiScore > 80) {
677
+ riskLevel = 'Extreme';
678
+ riskColor = 'red';
679
+ } else if (phiScore < 40 || phiScore > 60) {
680
+ riskLevel = 'High';
681
+ riskColor = 'orange';
682
+ } else {
683
+ riskLevel = 'Medium';
684
+ riskColor = 'yellow';
685
+ }
686
+
687
+ document.getElementById('risk-level').innerHTML = `<span class="px-2 py-1 rounded bg-opacity-20 bg-${riskColor}-500 text-${riskColor}-300">${riskLevel} Risk</span>`;
688
+
689
+ // Update BTC/ETH data
690
+ if (data.btc) {
691
+ document.getElementById('btc-price').textContent = `$${data.btc.price.toLocaleString()}`;
692
+ const btcChange = data.btc.change_24h;
693
+ const btcChangeEl = document.getElementById('btc-change');
694
+ btcChangeEl.textContent = `${btcChange > 0 ? '+' : ''}${btcChange.toFixed(2)}%`;
695
+ btcChangeEl.className = `ml-2 px-2 py-1 rounded text-xs ${btcChange >= 0 ? 'bg-green-500 bg-opacity-20 text-green-300' : 'bg-red-500 bg-opacity-20 text-red-300'}`;
696
+
697
+ document.getElementById('btc-dominance').textContent = data.btc.dominance.toFixed(1) + '%';
698
+ document.getElementById('btc-funding').textContent = (data.btc.funding_rate * 100).toFixed(4) + '%';
699
+ document.getElementById('btc-oi').textContent = `$${(data.btc.open_interest / 1000000000).toFixed(2)}B`;
700
+ document.getElementById('btc-liquidations').textContent = `$${(data.btc.liquidations / 1000000).toFixed(2)}M`;
701
+
702
+ // Update BTC chart
703
+ btcChart.data.datasets[0].data = data.btc.price_history || Array(24).fill(0);
704
+ btcChart.update();
705
+ }
706
+
707
+ if (data.eth) {
708
+ document.getElementById('eth-price').textContent = `$${data.eth.price.toLocaleString()}`;
709
+ const ethChange = data.eth.change_24h;
710
+ const ethChangeEl = document.getElementById('eth-change');
711
+ ethChangeEl.textContent = `${ethChange > 0 ? '+' : ''}${ethChange.toFixed(2)}%`;
712
+ ethChangeEl.className = `ml-2 px-2 py-1 rounded text-xs ${ethChange >= 0 ? 'bg-green-500 bg-opacity-20 text-green-300' : 'bg-red-500 bg-opacity-20 text-red-300'}`;
713
+
714
+ document.getElementById('eth-dominance').textContent = data.eth.dominance.toFixed(1) + '%';
715
+ document.getElementById('eth-funding').textContent = (data.eth.funding_rate * 100).toFixed(4) + '%';
716
+ document.getElementById('eth-oi').textContent = `$${(data.eth.open_interest / 1000000000).toFixed(2)}B`;
717
+ document.getElementById('eth-liquidations').textContent = `$${(data.eth.liquidations / 1000000).toFixed(2)}M`;
718
+
719
+ // Update ETH chart
720
+ ethChart.data.datasets[0].data = data.eth.price_history || Array(24).fill(0);
721
+ ethChart.update();
722
+ }
723
+
724
+ // Update long/short ratio
725
+ if (data.long_short_ratio) {
726
+ const ratio = data.long_short_ratio;
727
+ document.getElementById('ls-ratio-value').textContent = ratio.toFixed(2);
728
+ document.getElementById('long-bar').style.width = `${(ratio / (ratio + 1)) * 100}%`;
729
+ document.getElementById('short-bar').style.width = `${(1 / (ratio + 1)) * 100}%`;
730
+ }
731
+
732
+ // Update fear & greed index
733
+ if (data.fear_greed) {
734
+ const fg = data.fear_greed;
735
+ document.getElementById('fear-greed-value').textContent = `${fg.value} (${fg.label})`;
736
+ document.getElementById('fear-greed-bar').style.width = `${fg.value}%`;
737
+ }
738
+
739
+ // Update top gainers/losers
740
+ if (data.top_gainers) {
741
+ const gainersList = document.getElementById('gainers-list');
742
+ gainersList.innerHTML = '';
743
+
744
+ data.top_gainers.slice(0, 5).forEach(gainer => {
745
+ const gainerEl = document.createElement('div');
746
+ gainerEl.className = 'flex items-center justify-between p-3 rounded-lg hover:bg-gray-800 transition';
747
+
748
+ gainerEl.innerHTML = `
749
+ <div class="flex items-center">
750
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3 flex items-center justify-center text-xs font-bold">
751
+ ${gainer.symbol.substring(0, 3)}
752
+ </div>
753
+ <div>
754
+ <div class="font-medium">${gainer.symbol}</div>
755
+ <div class="text-xs text-gray-400">$${(gainer.price / 1000).toFixed(3)}K</div>
756
+ </div>
757
+ </div>
758
+ <div class="px-3 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 text-sm">
759
+ +${gainer.change.toFixed(2)}%
760
+ </div>
761
+ `;
762
+
763
+ gainersList.appendChild(gainerEl);
764
+ });
765
+ }
766
+
767
+ if (data.top_losers) {
768
+ const losersList = document.getElementById('losers-list');
769
+ losersList.innerHTML = '';
770
+
771
+ data.top_losers.slice(0, 5).forEach(loser => {
772
+ const loserEl = document.createElement('div');
773
+ loserEl.className = 'flex items-center justify-between p-3 rounded-lg hover:bg-gray-800 transition';
774
+
775
+ loserEl.innerHTML = `
776
+ <div class="flex items-center">
777
+ <div class="w-8 h-8 rounded-full bg-gray-700 mr-3 flex items-center justify-center text-xs font-bold">
778
+ ${loser.symbol.substring(0, 3)}
779
+ </div>
780
+ <div>
781
+ <div class="font-medium">${loser.symbol}</div>
782
+ <div class="text-xs text-gray-400">$${(loser.price / 1000).toFixed(3)}K</div>
783
+ </div>
784
+ </div>
785
+ <div class="px-3 py-1 rounded-full bg-opacity-20 bg-red-500 text-red-300 text-sm">
786
+ ${loser.change.toFixed(2)}%
787
+ </div>
788
+ `;
789
+
790
+ losersList.appendChild(loserEl);
791
+ });
792
+ }
793
+
794
+ // Update funding rates chart
795
+ if (data.funding_rates) {
796
+ fundingChart.data.datasets[0].data = Object.values(data.funding_rates);
797
+ fundingChart.update();
798
+ }
799
+
800
+ // Update open interest chart
801
+ if (data.open_interest) {
802
+ oiChart.data.datasets[0].data = data.open_interest.btc_history;
803
+ oiChart.data.datasets[1].data = data.open_interest.eth_history;
804
+ oiChart.update();
805
+ }
806
+
807
+ // Update liquidation chart
808
+ if (data.liquidations) {
809
+ liquidationChart.data.datasets[0].data = data.liquidations.longs;
810
+ liquidationChart.data.datasets[1].data = data.liquidations.shorts;
811
+ liquidationChart.update();
812
+ }
813
+ }
814
+
815
+ // Refresh button
816
+ document.getElementById('refresh-btn').addEventListener('click', fetchData);
817
+
818
+ // Initial load
819
+ document.addEventListener('DOMContentLoaded', () => {
820
+ feather.replace();
821
+ fetchData();
822
+
823
+ // Auto-refresh every 5 minutes
824
+ setInterval(fetchData, 5 * 60 * 1000);
825
+ });
826
+ </script>
827
+ </body>
828
  </html>