AI-Powered Geopolitical Risk Tracker for Investors

AI Geopolitical Risk Tracker

Navigate global markets by understanding and modeling geopolitical risks.

Step 1: Global Risk Dashboard

World Overview

Hover over or click a region for details.

Overall Risk: ${state.riskData[regionName].toFixed(1)} / 10

Political Stability: ${data.political} / 10

Economic Risk: ${data.economic} / 10

Social Unrest: ${data.social} / 10

`; }; // --- AI ANALYSIS --- window.getAIAnalysis = async () => { const btn = document.getElementById('ai-analysis-btn'); btn.disabled = true; document.getElementById('ai-btn-text').style.display = 'none'; document.getElementById('ai-spinner').style.display = 'inline-block'; const region = document.getElementById('ai-region-select').value; const riskType = document.getElementById('ai-risk-select').value; const regionData = REGION_DATA[region]; const prompt = ` Act as a geopolitical risk analyst for an investment firm. Analyze the following scenario and provide a brief for an investor. - Region of Interest: ${region} - Specific Risk to Analyze: ${riskType} - Internal Risk Scores for ${region}: Political=${regionData.political}, Economic=${regionData.economic}, Social=${regionData.social}. Please provide: 1. A brief "Executive Summary" of the situation. 2. A list of 2-3 "Key Drivers" for this risk. 3. A list of 2-3 potential "Investment Implications". Format the response in simple HTML using only

for titles and
  • for lists. `; try { const payload = { contents: [{ role: "user", parts: [{ text: prompt }] }] }; const apiKey = ""; // Provided by Canvas const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); let text = "Could not generate analysis. Please try again."; if (result.candidates && result.candidates[0].content && result.candidates[0].content.parts[0]) { text = result.candidates[0].content.parts[0].text; } state.aiAnalysisHTML = text; document.getElementById('ai-analysis-content').innerHTML = state.aiAnalysisHTML; document.getElementById('ai-analysis-container').classList.remove('hidden'); document.getElementById('summary-ai-content').innerHTML = state.aiAnalysisHTML; } finally { btn.disabled = false; document.getElementById('ai-btn-text').style.display = 'inline-block'; document.getElementById('ai-spinner').style.display = 'none'; } }; // --- PORTFOLIO IMPACT --- const updatePortfolioAllocation = () => { const sliders = document.querySelectorAll('#portfolio-sliders input'); let total = 0; sliders.forEach(slider => { const value = parseInt(slider.value); total += value; state.portfolio[slider.dataset.asset] = value / 100; }); const totalEl = document.getElementById('allocation-total'); totalEl.textContent = `Total: ${total}%`; totalEl.className = `text-center mt-4 font-bold ${total === 100 ? 'text-green-600' : 'text-red-600'}`; runImpactAnalysis(); // Re-run analysis on slider change }; const runImpactAnalysis = () => { state.shockScenario = document.getElementById('shock-scenario-select').value; const impacts = SHOCK_SCENARIOS[state.shockScenario]; const resultsContainer = document.getElementById('portfolio-impact-results'); let weightedImpact = 0; let resultsHTML = '
    '; for (const asset of PORTFOLIO_ASSETS) { const weight = state.portfolio[asset] || 0; const impact = impacts[asset] || 0; weightedImpact += weight * impact; resultsHTML += `
    ${asset} Impact: ${(impact * 100).toFixed(1)}%
    `; } resultsHTML += `
    Total Portfolio Impact: ${(weightedImpact * 100).toFixed(2)}%
    `; resultsHTML += '
    '; resultsContainer.innerHTML = resultsHTML; // Update summary tab content document.getElementById('summary-portfolio-content').innerHTML = resultsHTML; generateImpactChart(); }; // --- CHARTS & PDF --- const generateImpactChart = () => { const impacts = SHOCK_SCENARIOS[state.shockScenario]; const ctx = document.getElementById('impact-chart').getContext('2d'); const data = { labels: PORTFOLIO_ASSETS, datasets: [{ label: 'Projected Impact', data: PORTFOLIO_ASSETS.map(asset => (impacts[asset] || 0) * 100), backgroundColor: PORTFOLIO_ASSETS.map(asset => ((impacts[asset] || 0) >= 0 ? 'rgba(5, 150, 105, 0.6)' : 'rgba(220, 38, 38, 0.6)')) }] }; if (impactChart) impactChart.destroy(); impactChart = new Chart(ctx, { type: 'bar', data: data, options: { indexAxis: 'y', plugins: { legend: { display: false } }, scales: { x: { ticks: { callback: v => `${v}%`} } } } }); }; window.downloadPDF = async () => { const btn = document.querySelector('#pdf-button-container button'); btn.disabled = true; btn.textContent = 'Generating...'; const { jsPDF } = window.jspdf; const content = document.getElementById('summary-for-pdf'); try { const canvas = await html2canvas(content, { scale: 2 }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'landscape', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); let imgWidth = pdfWidth - 20; let imgHeight = canvas.height * imgWidth / canvas.width; pdf.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight); pdf.save(`Geopolitical_Risk_Report_${new Date().toISOString().slice(0, 10)}.pdf`); } finally { btn.disabled = false; btn.textContent = 'Download Report as PDF'; } }; init(); });

Scroll to Top