cryptopulse-navigator / index.html
roowoo's picture
please pull the data needed from binance api or cryptoglass.com
34912d5 verified
Raw
History Blame Contribute Delete
45.5 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CryptoPulse Navigator - Intelligent CoinGlass Dashboard</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<link rel="stylesheet" href="/static/style.css">
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CryptoPulse Navigator - Intelligent CoinGlass Dashboard</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#6366f1',
secondary: '#10b981',
dark: '#1e293b',
darker: '#0f172a'
}
}
}
}
</script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Space Grotesk', sans-serif;
}
.glass-card {
backdrop-filter: blur(16px) saturate(180%);
-webkit-backdrop-filter: blur(16px) saturate(180%);
background-color: rgba(30, 41, 59, 0.75);
border: 1px solid rgba(255, 255, 255, 0.125);
}
.phase-badge {
transition: all 0.3s ease;
}
.phase-badge:hover {
transform: scale(1.05);
}
</style>
</head>
<body class="bg-darker text-white min-h-screen">
<div id="vanta-bg" class="fixed inset-0 -z-10"></div>
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="flex justify-between items-center mb-8">
<div>
<h1 class="text-3xl font-bold flex items-center">
<i data-feather="activity" class="mr-2 text-primary"></i>
CryptoPulse <span class="text-primary">Navigator</span>
</h1>
<p class="text-gray-400">Intelligent CoinGlass Dashboard</p>
</div>
<div class="flex items-center space-x-4">
<div id="status-badge" class="px-3 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 flex items-center">
<span class="w-2 h-2 rounded-full bg-green-500 mr-2"></span>
<span>Live</span>
</div>
<div id="last-updated" class="text-gray-400 text-sm">
<i data-feather="clock" class="w-4 h-4 inline mr-1"></i>
<span>Updating...</span>
</div>
<button id="refresh-btn" class="p-2 rounded-full hover:bg-gray-800 transition">
<i data-feather="refresh-cw" class="w-5 h-5"></i>
</button>
</div>
</header>
<!-- PHI Score and Market Phase -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
<!-- PHI Score Card -->
<div class="glass-card p-6 rounded-xl col-span-1 lg:col-span-2">
<div class="flex justify-between items-start mb-4">
<div>
<h2 class="text-xl font-semibold">Market Health Index</h2>
<p class="text-gray-400 text-sm">PHI Score (Position Health Index)</p>
</div>
<div id="phase-badge" class="px-3 py-1 rounded-full bg-opacity-20 bg-secondary text-secondary phase-badge">
Loading...
</div>
</div>
<div class="flex items-center">
<div class="w-32 h-32 flex items-center justify-center relative">
<canvas id="phi-gauge" width="160" height="160"></canvas>
<div class="absolute text-center">
<div id="phi-score" class="text-4xl font-bold">--</div>
<div class="text-xs text-gray-400">PHI Score</div>
</div>
</div>
<div class="ml-6 flex-1">
<div class="mb-4">
<div class="flex justify-between text-sm mb-1">
<span>Volatility (VOLX)</span>
<span id="volx-value" class="font-medium">--</span>
</div>
<div class="w-full bg-gray-700 rounded-full h-2">
<div id="volx-bar" class="bg-yellow-500 h-2 rounded-full" style="width: 0%"></div>
</div>
</div>
<div class="mb-4">
<div class="flex justify-between text-sm mb-1">
<span>Momentum (MOMX)</span>
<span id="momx-value" class="font-medium">--</span>
</div>
<div class="w-full bg-gray-700 rounded-full h-2">
<div id="momx-bar" class="bg-blue-500 h-2 rounded-full" style="width: 0%"></div>
</div>
</div>
<div class="mb-4">
<div class="flex justify-between text-sm mb-1">
<span>Funding Bias (FBS)</span>
<span id="fbs-value" class="font-medium">--</span>
</div>
<div class="w-full bg-gray-700 rounded-full h-2">
<div id="fbs-bar" class="bg-purple-500 h-2 rounded-full" style="width: 0%"></div>
</div>
</div>
<div>
<div class="flex justify-between text-sm mb-1">
<span>Leverage (LPI)</span>
<span id="lpi-value" class="font-medium">--</span>
</div>
<div class="w-full bg-gray-700 rounded-full h-2">
<div id="lpi-bar" class="bg-red-500 h-2 rounded-full" style="width: 0%"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Market Overview -->
<div class="glass-card p-6 rounded-xl">
<h2 class="text-xl font-semibold mb-4">Market Overview</h2>
<div class="space-y-4">
<div>
<div class="flex justify-between text-sm mb-1">
<span>Long/Short Ratio</span>
<span id="ls-ratio-value" class="font-medium">--</span>
</div>
<div class="w-full h-3 bg-gray-700 rounded-full overflow-hidden">
<div class="h-full flex">
<div id="long-bar" class="bg-green-500" style="width: 50%"></div>
<div id="short-bar" class="bg-red-500" style="width: 50%"></div>
</div>
</div>
</div>
<div>
<div class="text-sm mb-1">Fear & Greed Index</div>
<div class="w-full bg-gray-700 rounded-full h-2">
<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>
</div>
<div id="fear-greed-value" class="text-right text-xs mt-1">--</div>
</div>
<div class="pt-2">
<div class="text-sm mb-1">Market Phase</div>
<div id="phase-description" class="text-sm text-gray-300">
Loading market phase description...
</div>
</div>
<div class="pt-2">
<div class="text-sm mb-1">Risk Level</div>
<div id="risk-level" class="text-sm font-medium">
<span class="px-2 py-1 rounded bg-opacity-20 bg-gray-500">Calculating...</span>
</div>
</div>
</div>
</div>
</div>
<!-- BTC/ETH Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
<!-- BTC Card -->
<div class="glass-card p-6 rounded-xl">
<div class="flex justify-between items-start mb-4">
<div class="flex items-center">
<img src="https://cryptologos.cc/logos/bitcoin-btc-logo.png" alt="BTC" class="w-8 h-8 mr-3">
<div>
<h2 class="text-xl font-semibold">Bitcoin</h2>
<div class="flex items-center">
<span id="btc-price" class="text-2xl font-bold">--</span>
<span id="btc-change" class="ml-2 px-2 py-1 rounded text-xs"></span>
</div>
</div>
</div>
<div class="text-xs text-gray-400">
Dominance: <span id="btc-dominance" class="font-medium">--%</span>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<div>
<div class="text-xs text-gray-400 mb-1">Funding Rate</div>
<div id="btc-funding" class="text-lg font-medium">--%</div>
</div>
<div>
<div class="text-xs text-gray-400 mb-1">Open Interest</div>
<div id="btc-oi" class="text-lg font-medium">--</div>
</div>
<div>
<div class="text-xs text-gray-400 mb-1">Liquidation</div>
<div class="flex items-center">
<span id="btc-liquidations" class="text-lg font-medium">--</span>
<span id="btc-liq-change" class="ml-1 text-xs"></span>
</div>
</div>
</div>
<div class="mt-4 h-20">
<canvas id="btc-chart"></canvas>
</div>
</div>
<!-- ETH Card -->
<div class="glass-card p-6 rounded-xl">
<div class="flex justify-between items-start mb-4">
<div class="flex items-center">
<img src="https://cryptologos.cc/logos/ethereum-eth-logo.png" alt="ETH" class="w-8 h-8 mr-3">
<div>
<h2 class="text-xl font-semibold">Ethereum</h2>
<div class="flex items-center">
<span id="eth-price" class="text-2xl font-bold">--</span>
<span id="eth-change" class="ml-2 px-2 py-1 rounded text-xs"></span>
</div>
</div>
</div>
<div class="text-xs text-gray-400">
Dominance: <span id="eth-dominance" class="font-medium">--%</span>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<div>
<div class="text-xs text-gray-400 mb-1">Funding Rate</div>
<div id="eth-funding" class="text-lg font-medium">--%</div>
</div>
<div>
<div class="text-xs text-gray-400 mb-1">Open Interest</div>
<div id="eth-oi" class="text-lg font-medium">--</div>
</div>
<div>
<div class="text-xs text-gray-400 mb-1">Liquidation</div>
<div class="flex items-center">
<span id="eth-liquidations" class="text-lg font-medium">--</span>
<span id="eth-liq-change" class="ml-1 text-xs"></span>
</div>
</div>
</div>
<div class="mt-4 h-20">
<canvas id="eth-chart"></canvas>
</div>
</div>
</div>
<!-- Gainers & Losers -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<!-- Top Gainers -->
<div class="glass-card p-6 rounded-xl">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold">Top Gainers</h2>
<span class="px-2 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 text-xs">24h</span>
</div>
<div id="gainers-list" class="space-y-3">
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
<div class="w-20 h-4 bg-gray-700 rounded"></div>
</div>
<div class="w-16 h-4 bg-gray-700 rounded"></div>
</div>
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
<div class="w-20 h-4 bg-gray-700 rounded"></div>
</div>
<div class="w-16 h-4 bg-gray-700 rounded"></div>
</div>
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
<div class="w-20 h-4 bg-gray-700 rounded"></div>
</div>
<div class="w-16 h-4 bg-gray-700 rounded"></div>
</div>
</div>
</div>
<!-- Top Losers -->
<div class="glass-card p-6 rounded-xl">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold">Top Losers</h2>
<span class="px-2 py-1 rounded-full bg-opacity-20 bg-red-500 text-red-300 text-xs">24h</span>
</div>
<div id="losers-list" class="space-y-3">
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
<div class="w-20 h-4 bg-gray-700 rounded"></div>
</div>
<div class="w-16 h-4 bg-gray-700 rounded"></div>
</div>
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
<div class="w-20 h-4 bg-gray-700 rounded"></div>
</div>
<div class="w-16 h-4 bg-gray-700 rounded"></div>
</div>
<div class="flex items-center justify-between p-3 rounded-lg bg-gray-800 bg-opacity-50 animate-pulse">
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3"></div>
<div class="w-20 h-4 bg-gray-700 rounded"></div>
</div>
<div class="w-16 h-4 bg-gray-700 rounded"></div>
</div>
</div>
</div>
</div>
<!-- Funding Rates & Open Interest -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<!-- Funding Rates -->
<div class="glass-card p-6 rounded-xl">
<h2 class="text-xl font-semibold mb-4">Exchange Funding Rates</h2>
<div class="h-64">
<canvas id="funding-chart"></canvas>
</div>
</div>
<!-- Open Interest -->
<div class="glass-card p-6 rounded-xl">
<h2 class="text-xl font-semibold mb-4">Open Interest</h2>
<div class="h-64">
<canvas id="oi-chart"></canvas>
</div>
</div>
</div>
<!-- Liquidation Heatmap -->
<div class="glass-card p-6 rounded-xl mb-8">
<h2 class="text-xl font-semibold mb-4">Liquidation Heatmap</h2>
<div class="h-80">
<canvas id="liquidation-chart"></canvas>
</div>
</div>
<!-- Footer -->
<footer class="text-center text-gray-500 text-sm py-6">
<div class="flex justify-center space-x-4 mb-2">
<a href="#" class="hover:text-primary transition"><i data-feather="github"></i></a>
<a href="#" class="hover:text-primary transition"><i data-feather="twitter"></i></a>
<a href="#" class="hover:text-primary transition"><i data-feather="discord"></i></a>
</div>
<p>CryptoPulse Navigator - Real-time Crypto Market Intelligence</p>
<p class="text-xs mt-1">Data sourced from CoinGlass | Updates every 5 minutes</p>
</footer>
</div>
<script>
// Global config with direct API endpoints
const CONFIG = {
refreshInterval: 60 * 1000, // 1 minute
apiEndpoints: {
binance: {
price: 'https://api.binance.com/api/v3/ticker/24hr',
klines: 'https://api.binance.com/api/v3/klines',
funding: 'https://fapi.binance.com/fapi/v1/premiumIndex'
},
coinGlass: {
openInterest: 'https://open-api.coinglass.com/api/pro/v1/futures/openInterest',
liquidation: 'https://open-api.coinglass.com/api/pro/v1/futures/liquidation',
fundingRates: 'https://open-api.coinglass.com/api/pro/v1/funding_rate',
longShort: 'https://open-api.coinglass.com/api/pro/v1/futures/longShort',
fearGreed: 'https://open-api.coinglass.com/api/pro/v1/fear_greed'
}
},
coinGlassKey: 'YOUR_COINGLASS_API_KEY' // Replace with actual key
};
// Initialize Vanta.js background
VANTA.NET({
el: "#vanta-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x6366f1,
backgroundColor: 0x0f172a,
points: 12.00,
maxDistance: 22.00,
spacing: 18.00
});
// Initialize charts
const phiCtx = document.getElementById('phi-gauge').getContext('2d');
const phiGauge = new Chart(phiCtx, {
type: 'doughnut',
data: {
datasets: [{
data: [0, 100],
backgroundColor: ['#6366f1', 'rgba(30, 41, 59, 0.5)'],
borderWidth: 0
}]
},
options: {
cutout: '85%',
rotation: -90,
circumference: 180,
responsive: false,
plugins: {
legend: { display: false },
tooltip: { enabled: false }
}
}
});
// Initialize other charts
const btcChart = new Chart(document.getElementById('btc-chart'), {
type: 'line',
data: {
labels: Array(24).fill(''),
datasets: [{
data: Array(24).fill(0),
borderColor: '#f59e0b',
borderWidth: 2,
tension: 0.3,
fill: true,
backgroundColor: 'rgba(245, 158, 11, 0.1)',
pointRadius: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: { legend: { display: false } },
scales: {
x: { display: false },
y: { display: false }
}
}
});
const ethChart = new Chart(document.getElementById('eth-chart'), {
type: 'line',
data: {
labels: Array(24).fill(''),
datasets: [{
data: Array(24).fill(0),
borderColor: '#8b5cf6',
borderWidth: 2,
tension: 0.3,
fill: true,
backgroundColor: 'rgba(139, 92, 246, 0.1)',
pointRadius: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: { legend: { display: false } },
scales: {
x: { display: false },
y: { display: false }
}
}
});
const fundingChart = new Chart(document.getElementById('funding-chart'), {
type: 'bar',
data: {
labels: ['Binance', 'OKX', 'Bybit', 'Deribit', 'Bitget'],
datasets: [{
label: 'Funding Rate',
data: [0.01, 0.005, 0.007, -0.002, 0.003],
backgroundColor: [
'rgba(99, 102, 241, 0.7)',
'rgba(99, 102, 241, 0.7)',
'rgba(99, 102, 241, 0.7)',
'rgba(99, 102, 241, 0.7)',
'rgba(99, 102, 241, 0.7)'
],
borderColor: [
'rgba(99, 102, 241, 1)',
'rgba(99, 102, 241, 1)',
'rgba(99, 102, 241, 1)',
'rgba(99, 102, 241, 1)',
'rgba(99, 102, 241, 1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: function(context) {
return (context.raw * 100).toFixed(4) + '%';
}
}
}
},
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return (value * 100).toFixed(2) + '%';
}
}
}
}
}
});
const oiChart = new Chart(document.getElementById('oi-chart'), {
type: 'line',
data: {
labels: ['6h ago', '5h ago', '4h ago', '3h ago', '2h ago', '1h ago', 'Now'],
datasets: [
{
label: 'BTC',
data: [12000, 12500, 12300, 12800, 12700, 13000, 13200],
borderColor: '#f59e0b',
backgroundColor: 'rgba(245, 158, 11, 0.1)',
tension: 0.3,
fill: true
},
{
label: 'ETH',
data: [8000, 8200, 8100, 8300, 8250, 8400, 8500],
borderColor: '#8b5cf6',
backgroundColor: 'rgba(139, 92, 246, 0.1)',
tension: 0.3,
fill: true
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': $' + context.raw.toLocaleString();
}
}
}
},
scales: {
y: {
ticks: {
callback: function(value) {
return '$' + (value / 1000) + 'B';
}
}
}
}
}
});
const liquidationChart = new Chart(document.getElementById('liquidation-chart'), {
type: 'bar',
data: {
labels: ['BTC', 'ETH', 'SOL', 'XRP', 'ADA', 'DOT', 'DOGE', 'MATIC'],
datasets: [
{
label: 'Long',
data: [12000000, 8500000, 3200000, 1800000, 1500000, 1200000, 900000, 800000],
backgroundColor: 'rgba(16, 185, 129, 0.7)',
borderColor: 'rgba(16, 185, 129, 1)',
borderWidth: 1
},
{
label: 'Short',
data: [9500000, 7200000, 2800000, 1500000, 1200000, 900000, 700000, 600000],
backgroundColor: 'rgba(239, 68, 68, 0.7)',
borderColor: 'rgba(239, 68, 68, 1)',
borderWidth: 1
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
callbacks: {
label: function(context) {
return context.dataset.label + ': $' + (context.raw / 1000000).toFixed(2) + 'M';
}
}
}
},
scales: {
x: { stacked: true },
y: {
stacked: true,
ticks: {
callback: function(value) {
return '$' + (value / 1000000) + 'M';
}
}
}
}
}
});
// Fetch live data from Binance and CoinGlass APIs
async function fetchData() {
try {
document.getElementById('status-badge').className = 'px-3 py-1 rounded-full bg-opacity-20 bg-yellow-500 text-yellow-300 flex items-center';
document.querySelector('#status-badge span:last-child').textContent = 'Updating';
// Binance API requests
const [binancePrices, btcFunding, ethFunding] = await Promise.all([
axios.get(`${CONFIG.apiEndpoints.binance.price}?symbols=["BTCUSDT","ETHUSDT"]`),
axios.get(`${CONFIG.apiEndpoints.binance.funding}?symbol=BTCUSDT`),
axios.get(`${CONFIG.apiEndpoints.binance.funding}?symbol=ETHUSDT`)
]);
// CoinGlass API requests with headers
const coinGlassHeaders = {
'coinglassSecret': CONFIG.coinGlassKey
};
const [openInterest, liquidations, fundingRates, longShort, fearGreed] = await Promise.all([
axios.get(CONFIG.apiEndpoints.coinGlass.openInterest, { headers: coinGlassHeaders }),
axios.get(CONFIG.apiEndpoints.coinGlass.liquidation, { headers: coinGlassHeaders }),
axios.get(CONFIG.apiEndpoints.coinGlass.fundingRates, { headers: coinGlassHeaders }),
axios.get(CONFIG.apiEndpoints.coinGlass.longShort, { headers: coinGlassHeaders }),
axios.get(CONFIG.apiEndpoints.coinGlass.fearGreed, { headers: coinGlassHeaders })
]);
// Process Binance data
const btcData = binancePrices.data.find(p => p.symbol === 'BTCUSDT');
const ethData = binancePrices.data.find(p => p.symbol === 'ETHUSDT');
// Transform data into our format
const transformedData = {
btc: {
price: parseFloat(btcData.lastPrice),
change_24h: parseFloat(btcData.priceChangePercent),
funding_rate: parseFloat(btcFunding.data.lastFundingRate) * 100,
open_interest: openInterest.data.data.btc.sumOpenInterest,
liquidations: liquidations.data.data.btc.sumLiquidation
},
eth: {
price: parseFloat(ethData.lastPrice),
change_24h: parseFloat(ethData.priceChangePercent),
funding_rate: parseFloat(ethFunding.data.lastFundingRate) * 100,
open_interest: openInterest.data.data.eth.sumOpenInterest,
liquidations: liquidations.data.data.eth.sumLiquidation
},
phi_score: calculatePHIScore(longShort.data.data), // Calculated score
volx: parseFloat(fearGreed.data.data.volatility),
momx: parseFloat(fearGreed.data.data.momentum),
fbs: parseFloat(fundingRates.data.data.averageRate),
lpi: parseFloat(longShort.data.data.longShortRate),
long_short_ratio: parseFloat(longShort.data.data.longShortRate),
fear_greed: {
value: parseFloat(fearGreed.data.data.value),
label: fearGreed.data.data.valueClass
},
funding_rates: fundingRates.data.data.rateList,
open_interest_history: openInterest.data.data.historyList,
liquidations_history: liquidations.data.data.historyList
};
// Helper function to calculate PHI score
function calculatePHIScore(longShortData) {
// Weighted average of multiple factors
const volScore = (parseFloat(longShortData.volatility) / 100) * 30;
const momScore = (parseFloat(longShortData.momentum) + 1) * 25;
const lsScore = (parseFloat(longShortData.longShortRate) - 1) * 15;
const fgScore = (parseFloat(fearGreed.data.data.value) / 100) * 30;
return Math.min(100, Math.max(0,
volScore + momScore + lsScore + fgScore
)).toFixed(1);
}
updateDashboard(transformedData);
document.getElementById('status-badge').className = 'px-3 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 flex items-center';
document.querySelector('#status-badge span:last-child').textContent = 'Live';
document.getElementById('last-updated').innerHTML = `<i data-feather="clock" class="w-4 h-4 inline mr-1"></i> ${new Date().toLocaleTimeString()}`;
} catch (error) {
console.error('Error fetching data:', error);
document.getElementById('status-badge').className = 'px-3 py-1 rounded-full bg-opacity-20 bg-red-500 text-red-300 flex items-center';
document.querySelector('#status-badge span:last-child').textContent = 'Offline';
// Try again in 30 seconds if failed
setTimeout(fetchData, 30000);
}
}
// Update dashboard with real data
function updateDashboard(data) {
// Update timestamp first
document.getElementById('last-updated').innerHTML =
`<i data-feather="clock" class="w-4 h-4 inline mr-1"></i> ${new Date().toLocaleTimeString()}`;
// PHI Score and Metrics
const phiScore = data.phi_score || 50;
document.getElementById('phi-score').textContent = phiScore.toFixed(1);
// Update gauge chart
phiGauge.data.datasets[0].data = [phiScore, 100 - phiScore];
phiGauge.update();
// Update metric bars
document.getElementById('volx-value').textContent = data.volx ? data.volx.toFixed(1) : '--';
document.getElementById('momx-value').textContent = data.momx ? (data.momx * 100).toFixed(2) + '%' : '--';
document.getElementById('fbs-value').textContent = data.fbs ? (data.fbs * 100).toFixed(4) + '%' : '--';
document.getElementById('lpi-value').textContent = data.lpi ? data.lpi.toFixed(1) : '--';
document.getElementById('volx-bar').style.width = `${data.volx || 0}%`;
document.getElementById('momx-bar').style.width = `${(data.momx || 0) * 100}%`;
document.getElementById('fbs-bar').style.width = `${(data.fbs || 0) * 100}%`;
document.getElementById('lpi-bar').style.width = `${data.lpi || 0}%`;
// Update market phase
let phase = 'Neutral';
let phaseColor = 'gray';
if (phiScore < 30) {
phase = 'Compression';
phaseColor = 'purple';
} else if (phiScore < 50) {
phase = 'Recovery';
phaseColor = 'blue';
} else if (phiScore < 70) {
phase = 'Expansion';
phaseColor = 'green';
} else {
phase = 'Exhaustion';
phaseColor = 'red';
}
const phaseBadge = document.getElementById('phase-badge');
phaseBadge.textContent = phase;
phaseBadge.className = `px-3 py-1 rounded-full bg-opacity-20 bg-${phaseColor}-500 text-${phaseColor}-300 phase-badge`;
// Update phase description
const descriptions = {
'Compression': 'Market is in a compression phase with low volatility. Traders are cautious, awaiting a breakout.',
'Recovery': 'Market is recovering from recent moves. Volatility is increasing as traders reposition.',
'Expansion': 'Market is in expansion with strong momentum. Trending conditions likely to continue.',
'Exhaustion': 'Market shows signs of exhaustion after strong moves. Potential reversal or consolidation ahead.',
'Neutral': 'Market is in neutral territory without clear direction. Watch for breakout signals.'
};
document.getElementById('phase-description').textContent = descriptions[phase] || descriptions['Neutral'];
// Update risk level
let riskLevel = 'Medium';
let riskColor = 'yellow';
if (phiScore < 20 || phiScore > 80) {
riskLevel = 'Extreme';
riskColor = 'red';
} else if (phiScore < 40 || phiScore > 60) {
riskLevel = 'High';
riskColor = 'orange';
} else {
riskLevel = 'Medium';
riskColor = 'yellow';
}
document.getElementById('risk-level').innerHTML = `<span class="px-2 py-1 rounded bg-opacity-20 bg-${riskColor}-500 text-${riskColor}-300">${riskLevel} Risk</span>`;
// Update BTC/ETH data
if (data.btc) {
document.getElementById('btc-price').textContent = `$${data.btc.price.toLocaleString()}`;
const btcChange = data.btc.change_24h;
const btcChangeEl = document.getElementById('btc-change');
btcChangeEl.textContent = `${btcChange > 0 ? '+' : ''}${btcChange.toFixed(2)}%`;
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'}`;
document.getElementById('btc-dominance').textContent = data.btc.dominance.toFixed(1) + '%';
document.getElementById('btc-funding').textContent = (data.btc.funding_rate * 100).toFixed(4) + '%';
document.getElementById('btc-oi').textContent = `$${(data.btc.open_interest / 1000000000).toFixed(2)}B`;
document.getElementById('btc-liquidations').textContent = `$${(data.btc.liquidations / 1000000).toFixed(2)}M`;
// Update BTC chart
btcChart.data.datasets[0].data = data.btc.price_history || Array(24).fill(0);
btcChart.update();
}
if (data.eth) {
document.getElementById('eth-price').textContent = `$${data.eth.price.toLocaleString()}`;
const ethChange = data.eth.change_24h;
const ethChangeEl = document.getElementById('eth-change');
ethChangeEl.textContent = `${ethChange > 0 ? '+' : ''}${ethChange.toFixed(2)}%`;
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'}`;
document.getElementById('eth-dominance').textContent = data.eth.dominance.toFixed(1) + '%';
document.getElementById('eth-funding').textContent = (data.eth.funding_rate * 100).toFixed(4) + '%';
document.getElementById('eth-oi').textContent = `$${(data.eth.open_interest / 1000000000).toFixed(2)}B`;
document.getElementById('eth-liquidations').textContent = `$${(data.eth.liquidations / 1000000).toFixed(2)}M`;
// Update ETH chart
ethChart.data.datasets[0].data = data.eth.price_history || Array(24).fill(0);
ethChart.update();
}
// Update long/short ratio
if (data.long_short_ratio) {
const ratio = data.long_short_ratio;
document.getElementById('ls-ratio-value').textContent = ratio.toFixed(2);
document.getElementById('long-bar').style.width = `${(ratio / (ratio + 1)) * 100}%`;
document.getElementById('short-bar').style.width = `${(1 / (ratio + 1)) * 100}%`;
}
// Update fear & greed index
if (data.fear_greed) {
const fg = data.fear_greed;
document.getElementById('fear-greed-value').textContent = `${fg.value} (${fg.label})`;
document.getElementById('fear-greed-bar').style.width = `${fg.value}%`;
}
// Update top gainers/losers
if (data.top_gainers) {
const gainersList = document.getElementById('gainers-list');
gainersList.innerHTML = '';
data.top_gainers.slice(0, 5).forEach(gainer => {
const gainerEl = document.createElement('div');
gainerEl.className = 'flex items-center justify-between p-3 rounded-lg hover:bg-gray-800 transition';
gainerEl.innerHTML = `
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3 flex items-center justify-center text-xs font-bold">
${gainer.symbol.substring(0, 3)}
</div>
<div>
<div class="font-medium">${gainer.symbol}</div>
<div class="text-xs text-gray-400">$${(gainer.price / 1000).toFixed(3)}K</div>
</div>
</div>
<div class="px-3 py-1 rounded-full bg-opacity-20 bg-green-500 text-green-300 text-sm">
+${gainer.change.toFixed(2)}%
</div>
`;
gainersList.appendChild(gainerEl);
});
}
if (data.top_losers) {
const losersList = document.getElementById('losers-list');
losersList.innerHTML = '';
data.top_losers.slice(0, 5).forEach(loser => {
const loserEl = document.createElement('div');
loserEl.className = 'flex items-center justify-between p-3 rounded-lg hover:bg-gray-800 transition';
loserEl.innerHTML = `
<div class="flex items-center">
<div class="w-8 h-8 rounded-full bg-gray-700 mr-3 flex items-center justify-center text-xs font-bold">
${loser.symbol.substring(0, 3)}
</div>
<div>
<div class="font-medium">${loser.symbol}</div>
<div class="text-xs text-gray-400">$${(loser.price / 1000).toFixed(3)}K</div>
</div>
</div>
<div class="px-3 py-1 rounded-full bg-opacity-20 bg-red-500 text-red-300 text-sm">
${loser.change.toFixed(2)}%
</div>
`;
losersList.appendChild(loserEl);
});
}
// Update funding rates chart
if (data.funding_rates) {
fundingChart.data.datasets[0].data = Object.values(data.funding_rates);
fundingChart.update();
}
// Update open interest chart
if (data.open_interest) {
oiChart.data.datasets[0].data = data.open_interest.btc_history;
oiChart.data.datasets[1].data = data.open_interest.eth_history;
oiChart.update();
}
// Update liquidation chart
if (data.liquidations) {
liquidationChart.data.datasets[0].data = data.liquidations.longs;
liquidationChart.data.datasets[1].data = data.liquidations.shorts;
liquidationChart.update();
}
}
// Refresh button
document.getElementById('refresh-btn').addEventListener('click', fetchData);
// Initial load with error handling
document.addEventListener('DOMContentLoaded', () => {
feather.replace();
// Add CORS proxy header if needed
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// First try with proxy
fetchData();
// Auto-refresh every minute
setInterval(fetchData, CONFIG.refreshInterval);
// Fallback: if CORS proxy fails, try direct with JSONP
window.jsonpCallback = function(data) {
console.log('JSONP fallback data:', data);
// Transform and use data as needed
};
});
// Fallback JSONP function
function loadJSONP(url) {
const script = document.createElement('script');
script.src = url;
document.head.appendChild(script);
}
</script>
</body>
</html>