Live Forex

Live Forex Dashboard - JobH9

Majors & Crosses

Loading Rates & Charts...

Technical Analysis (RSI)

Calculating RSI...

Market Sentiment

Analyzing Sentiment...

Latest Stories

Loading News...

Economic Calendar (Next 7 Days)

Loading Calendar...

Loading Rates & Charts...

'; try { const [ratesResponse, ...historicalResponses] = await Promise.all([ fetch(`https://financialmodelingprep.com/api/v3/fx/${pairs.join(',')}?apikey=${apiKey}`), ...pairs.map(pair => fetch(`https://financialmodelingprep.com/api/v3/historical-chart/5min/${pair}?apikey=${apiKey}`)) ]); const ratesData = await ratesResponse.json(); const historicalData = await Promise.all(historicalResponses.map(res => res.json())); ratesGrid.innerHTML = ''; if (Array.isArray(ratesData)) { ratesData.forEach((rate, index) => { const history = historicalData[index]; createRateCard(rate, history); }); } else { throw new Error(ratesData['Error Message'] || "Invalid data format for rates."); } } catch (error) { ratesGrid.innerHTML = `

Could not load rates. Reason: ${error.message}

`; console.error('Error fetching data:', error); } } function createRateCard(rate, history) { const ratesGrid = document.getElementById('ratesGrid'); const changeClass = rate.changes > 0 ? 'positive' : 'negative'; const arrow = rate.changes > 0 ? '' : ''; const safeTicker = rate.ticker.replace('/', ''); const card = document.createElement('div'); card.className = 'rate-card'; card.id = `rate-${safeTicker}`; card.innerHTML = `
${rate.ticker} ${arrow}
${rate.bid.toFixed(4)}
`; ratesGrid.appendChild(card); renderMiniChart(safeTicker, history); } function renderMiniChart(ticker, history) { if (!history || history.length === 0) return; const seriesData = history.slice(0, 20).reverse().map(d => ({ x: new Date(d.date), y: [d.open, d.high, d.low, d.close] })); const options = { series: [{ data: seriesData }], chart: { type: 'candlestick', height: 60, sparkline: { enabled: true } }, tooltip: { enabled: false }, xaxis: { type: 'datetime' }, yaxis: { reversed: false }, stroke: { width: 1.2, colors: ['#555'] }, plotOptions: { candlestick: { colors: { upward: '#1e8e3e', downward: '#d93025' }, wick: { useFillColor: true } } } }; const chartElement = document.querySelector(`#chart-${ticker}`); if (chartElement) { const chart = new ApexCharts(chartElement, options); chart.render(); } } // --- 2. Fetch Latest News --- async function fetchForexNews() { const newsList = document.getElementById('newsList'); const apiUrl = `https://financialmodelingprep.com/api/v3/fmp/articles?page=0&size=10&apikey=${apiKey}`; try { const response = await fetch(apiUrl); const data = await response.json(); newsList.innerHTML = ''; if (data && Array.isArray(data.content)) { data.content.forEach(article => { const item = document.createElement('div'); item.className = 'news-item'; item.innerHTML = `

${article.title}

From ${article.site} | ${new Date(article.date).toLocaleDateString()}
`; newsList.appendChild(item); }); } else { throw new Error(data['Error Message'] || "Invalid data format for news."); } } catch (error) { newsList.innerHTML = `

Could not load news. Reason: ${error.message}

`; console.error('Error fetching news:', error); } } // --- 3. Fetch Economic Calendar --- async function fetchEconomicCalendar() { const calendarContainer = document.getElementById('calendarContainer'); const today = new Date(); const nextWeek = new Date(); nextWeek.setDate(today.getDate() + 7); const fromDate = today.toISOString().split('T')[0]; const toDate = nextWeek.toISOString().split('T')[0]; const apiUrl = `https://financialmodelingprep.com/api/v3/economic_calendar?from=${fromDate}&to=${toDate}&apikey=${apiKey}`; try { const response = await fetch(apiUrl); const data = await response.json(); calendarContainer.innerHTML = ''; const table = document.createElement('table'); table.className = 'calendar-table'; table.innerHTML = `DateCurrencyEventImpactActualForecastPrevious`; const tbody = table.querySelector('tbody'); if (data && data.length > 0) { data.forEach(event => { const eventDate = new Date(event.date).toLocaleDateString([], { month: 'short', day: 'numeric' }); const impactClass = event.impact ? event.impact.charAt(0).toUpperCase() + event.impact.slice(1) : 'Low'; const row = document.createElement('tr'); row.innerHTML = `${eventDate}${event.currency}${event.event}${event.actual === null ? '-' : event.actual}${event.estimate === null ? '-' : event.estimate}${event.previous === null ? '-' : event.previous}`; tbody.appendChild(row); }); } else { tbody.innerHTML = 'No major events scheduled for the next 7 days.'; } calendarContainer.appendChild(table); } catch (error) { calendarContainer.innerHTML = '

Could not load economic calendar.

'; console.error('Error fetching calendar:', error); } } // --- 4. Fetch Technical Analysis --- async function fetchTechnicalAnalysis() { const container = document.getElementById('techAnalysisContainer'); try { const table = document.createElement('table'); table.className = 'tech-analysis-table'; table.innerHTML = `PairRSI (14 Day)Signal`; const tbody = table.querySelector('tbody'); for (const pair of pairs) { const response = await fetch(`https://financialmodelingprep.com/api/v3/technical_indicator/daily/${pair}?period=14&type=rsi&apikey=${apiKey}`); const data = await response.json(); if (data && data.length > 0) { const rsi = data[0].rsi.toFixed(2); let signal = 'Neutral'; let signalClass = 'neutral'; if (rsi > 70) { signal = 'Overbought'; signalClass = 'overbought'; } if (rsi < 30) { signal = 'Oversold'; signalClass = 'oversold'; } const row = document.createElement('tr'); row.innerHTML = `${pair}${rsi}${signal}`; tbody.appendChild(row); } } container.innerHTML = ''; container.appendChild(table); } catch (error) { container.innerHTML = '

Could not load technical analysis.

'; console.error('Error fetching RSI:', error); } } // --- 5. Fetch Market Sentiment --- async function fetchMarketSentiment() { const container = document.getElementById('sentimentContainer'); const apiUrl = `https://financialmodelingprep.com/api/v3/social-sentiment/trending?apikey=${apiKey}`; try { const response = await fetch(apiUrl); const data = await response.json(); let bullishCount = 0; let bearishCount = 0; if (Array.isArray(data)) { data.slice(0, 20).forEach(item => { if (item.sentiment > 0.1) bullishCount++; else if (item.sentiment < -0.1) bearishCount++; }); } else { throw new Error(data['Error Message'] || "Invalid data format for sentiment."); } let sentiment = 'Neutral'; let sentimentClass = 'neutral'; if (bullishCount > bearishCount) { sentiment = 'Bullish'; sentimentClass = 'bullish'; } if (bearishCount > bullishCount) { sentiment = 'Bearish'; sentimentClass = 'bearish'; } container.innerHTML = `

Overall Market Mood

${sentiment}

Based on social media and news analysis.

`; } catch (error) { container.innerHTML = `

Could not load sentiment. Reason: ${error.message}

`; console.error('Error fetching sentiment:', error); } } // --- Scroll Animation Logic --- const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('is-visible'); observer.unobserve(entry.target); } }); }, { threshold: 0.1 }); document.querySelectorAll('.animate-on-scroll').forEach(el => { observer.observe(el); }); // --- Initial Load --- fetchForexData(); fetchForexNews(); fetchEconomicCalendar(); fetchTechnicalAnalysis(); fetchMarketSentiment(); });