Spaces:
Sleeping
Sleeping
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Forex Sentinel | Intelligence Hub</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --glass-bg: rgba(255, 255, 255, 0.05); | |
| --glass-border: rgba(255, 255, 255, 0.1); | |
| --accent-blue: #007AFF; | |
| --accent-gold: #FFD700; | |
| --accent-green: #34C759; | |
| --accent-red: #FF3B30; | |
| --text-main: #FFFFFF; | |
| --text-dim: rgba(255, 255, 255, 0.6); | |
| } | |
| * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', sans-serif; } | |
| body { | |
| background: radial-gradient(circle at top right, #1a1a2e, #0f0f1b, #000000); | |
| color: var(--text-main); | |
| min-height: 100vh; | |
| padding: 40px 20px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| .bg-glow { | |
| position: fixed; width: 600px; height: 600px; | |
| background: radial-gradient(circle, rgba(0, 122, 255, 0.15) 0%, transparent 70%); | |
| top: -100px; right: -100px; z-index: -1; filter: blur(80px); | |
| } | |
| .header { text-align: center; margin-bottom: 40px; } | |
| .header h1 { font-size: 2.5rem; letter-spacing: -1px; background: linear-gradient(to bottom, #fff, #999); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } | |
| .header p { color: var(--text-dim); text-transform: uppercase; letter-spacing: 2px; font-size: 0.8rem; } | |
| .dashboard { display: grid; grid-template-columns: 1fr 1.5fr; gap: 30px; max-width: 1200px; width: 100%; } | |
| .glass-card { | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 24px; | |
| padding: 25px; | |
| box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); | |
| } | |
| .price-item { | |
| display: flex; justify-content: space-between; align-items: center; | |
| padding: 20px; border-radius: 16px; background: rgba(255, 255, 255, 0.03); | |
| margin-bottom: 15px; transition: transform 0.2s; | |
| } | |
| .price-item:hover { transform: scale(1.02); } | |
| .price-value { font-size: 1.6rem; font-weight: 700; font-variant-numeric: tabular-nums; } | |
| .recommendation-banner { | |
| background: linear-gradient(135deg, rgba(0, 122, 255, 0.2), rgba(255, 255, 255, 0.05)); | |
| border: 1px solid var(--accent-blue); | |
| padding: 20px; border-radius: 20px; margin-bottom: 20px; | |
| text-align: center; | |
| } | |
| .rec-action { | |
| font-size: 1.8rem; font-weight: 800; text-transform: uppercase; | |
| letter-spacing: 1px; margin: 10px 0; | |
| color: var(--accent-gold); | |
| } | |
| .impact-badge { | |
| display: inline-block; padding: 4px 12px; border-radius: 20px; | |
| font-size: 0.75rem; font-weight: 700; margin-right: 8px; | |
| } | |
| .bullish { background: rgba(52, 199, 89, 0.2); color: var(--accent-green); } | |
| .bearish { background: rgba(255, 59, 48, 0.2); color: var(--accent-red); } | |
| .neutral { background: rgba(255, 255, 255, 0.1); color: var(--text-dim); } | |
| .news-card { padding: 15px; border-radius: 12px; background: rgba(255, 255, 255, 0.02); border: 1px solid var(--glass-border); margin-bottom: 10px; } | |
| .news-card h4 { font-size: 0.9rem; font-weight: 600; margin-bottom: 5px; } | |
| .news-meta { font-size: 0.7rem; color: var(--text-dim); } | |
| .price-up { color: var(--accent-green); text-shadow: 0 0 10px var(--accent-green); } | |
| .price-down { color: var(--accent-red); text-shadow: 0 0 10px var(--accent-red); } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="bg-glow"></div> | |
| <div class="header"> | |
| <p>Live Market Intelligence • Kafka Powered</p> | |
| <h1>Sentinel Terminal</h1> | |
| </div> | |
| <div class="dashboard"> | |
| <div class="market-section"> | |
| <div class="glass-card"> | |
| <h3 style="margin-bottom: 20px;">Asset Tracking</h3> | |
| <div class="price-item"> | |
| <div> | |
| <div style="font-weight: 600;">Gold Spot (XAU/USD)</div> | |
| <div class="news-meta">Prix pour 1 once d'or</div> | |
| </div> | |
| <div class="price-value" id="price-XAU">0.00</div> | |
| </div> | |
| <div class="price-item"> | |
| <div> | |
| <div style="font-weight: 600;">Euro (EUR/USD)</div> | |
| <div class="news-meta">Valeur de 1€ en Dollars</div> | |
| </div> | |
| <div class="price-value" id="price-EUR">0.0000</div> | |
| </div> | |
| <div style="margin-top: 20px; font-size: 0.8rem; color: var(--text-dim);"> | |
| <p>💡 <b>XAU</b> monte = L'or se renforce.</p> | |
| <p>💡 <b>EUR</b> baisse = Le Dollar se renforce.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="intelligence-section"> | |
| <div class="glass-card"> | |
| <div class="recommendation-banner"> | |
| <p style="font-size: 0.8rem; text-transform: uppercase; color: var(--accent-blue);">Conseil IA Expert</p> | |
| <div class="rec-action" id="ai-rec">OBSERVATION</div> | |
| <div id="ai-reason" style="font-size: 0.9rem; opacity: 0.9;">Analyse du marché en cours...</div> | |
| </div> | |
| <div id="news-details"> | |
| <h4 id="news-title" style="margin-bottom: 10px;">En attente de nouvelles...</h4> | |
| <div style="display: flex; gap: 10px; margin-bottom: 15px;"> | |
| <span id="badge-gold" class="impact-badge neutral">GOLD: -</span> | |
| <span id="badge-eur" class="impact-badge neutral">EURO: -</span> | |
| </div> | |
| <div style="padding: 15px; background: rgba(0,0,0,0.2); border-radius: 12px; font-size: 0.9rem; border-left: 3px solid var(--accent-gold);"> | |
| <b>Prévision :</b> <span id="ai-forecast">-</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws'; | |
| const wsHost = window.location.host; // inclus host[:port] si nécessaire | |
| const socket = new WebSocket(`${wsProtocol}://${wsHost}/ws`); | |
| let lastPrices = { 'XAU/USD': 0, 'EUR/USD': 0 }; | |
| socket.onmessage = function(event) { | |
| const data = JSON.parse(event.data); | |
| if (data.topic === 'market-data') updatePrice(data.asset, data.price); | |
| if (data.topic === 'analyzed-news') updateAI(data); | |
| }; | |
| function updatePrice(asset, price) { | |
| const id = asset === 'XAU/USD' ? 'price-XAU' : 'price-EUR'; | |
| const el = document.getElementById(id); | |
| if (price > lastPrices[asset]) { el.className = 'price-value price-up'; } | |
| else if (price < lastPrices[asset]) { el.className = 'price-value price-down'; } | |
| el.innerText = price.toFixed(asset === 'XAU/USD' ? 2 : 4); | |
| lastPrices[asset] = price; | |
| } | |
| function updateAI(data) { | |
| document.getElementById('ai-rec').innerText = data.recommendation; | |
| document.getElementById('ai-reason').innerText = data.reason; | |
| document.getElementById('news-title').innerText = data.headline; | |
| document.getElementById('ai-forecast').innerText = data.forecast; | |
| const bGold = document.getElementById('badge-gold'); | |
| bGold.innerText = `GOLD: ${data.impact_gold}`; | |
| bGold.className = `impact-badge ${data.impact_gold.toLowerCase()}`; | |
| const bEur = document.getElementById('badge-eur'); | |
| bEur.innerText = `EURO: ${data.impact_eur}`; | |
| bEur.className = `impact-badge ${data.impact_eur.toLowerCase()}`; | |
| // Animation de mise à jour | |
| const banner = document.querySelector('.recommendation-banner'); | |
| banner.style.boxShadow = "0 0 30px rgba(0, 122, 255, 0.4)"; | |
| setTimeout(() => banner.style.boxShadow = "none", 1000); | |
| } | |
| </script> | |
| </body> | |
| </html> | |