Stock Market Event Impact Estimator

Stock Market Event Impact Estimator

Impact: ${formatImpact(impactResults.worstCaseImpact)}

Current Portfolio Value

${formatCurrency(impactResults.currentValue)}

Best-Case Scenario (${impactResults.bestCase}%)

${formatCurrency(impactResults.bestCaseValue)}

Impact: ${formatImpact(impactResults.bestCaseImpact)}

Detailed Stock Breakdown

${impactResults.details.map(d => ` `).join('')}
Ticker Current Value Worst-Case Impact Best-Case Impact
${d.ticker} ${formatCurrency(d.currentValue)} ${formatImpact(d.worstCaseImpact)} ${formatImpact(d.bestCaseImpact)}
`; }; const renderPortfolioTab = () => { let stockForms = portfolio.map(stock => `

Edit Holding

`).join(''); return `
${stockForms}
`; }; const renderEventTab = () => { return `
%
%
`; }; // --- DATA & EVENT HANDLERS --- window.addStock = () => { portfolio.push({ id: Date.now(), ticker: 'NEW', shares: 0, avgPrice: 0 }); renderCurrentTab(); }; window.updateStock = (id, key, value) => { const stock = portfolio.find(s => s.id === id); if(stock) stock[key] = (key === 'ticker') ? value : parseFloat(value) || 0; }; window.deleteStock = (id) => { portfolio = portfolio.filter(s => s.id !== id); renderCurrentTab(); }; window.updateEvent = (key, value) => { eventScenario[key] = (key === 'eventName') ? value : parseFloat(value) || 0; }; const handleImpactCalculation = () => { let currentValue = 0; let bestCaseValue = 0; let worstCaseValue = 0; const details = []; portfolio.forEach(stock => { const stockValue = stock.shares * stock.avgPrice; const bestImpact = stockValue * (eventScenario.bestCase / 100); const worstImpact = stockValue * (eventScenario.worstCase / 100); currentValue += stockValue; bestCaseValue += stockValue + bestImpact; worstCaseValue += stockValue + worstImpact; details.push({ ticker: stock.ticker, currentValue: stockValue, bestCaseImpact: bestImpact, worstCaseImpact: worstImpact }); }); impactResults = { eventName: eventScenario.eventName, bestCase: eventScenario.bestCase, worstCase: eventScenario.worstCase, currentValue, bestCaseValue, worstCaseValue, bestCaseImpact: bestCaseValue - currentValue, worstCaseImpact: worstCaseValue - currentValue, details }; switchTab(0); }; // --- CHART & PDF --- const renderChart = () => { if (impactChart) impactChart.destroy(); const ctx = document.getElementById('impactChart')?.getContext('2d'); if (!ctx || !impactResults) return; impactChart = new Chart(ctx, { type: 'bar', data: { labels: ['Portfolio Value'], datasets: [ { label: 'Worst Case', data: [impactResults.worstCaseValue], backgroundColor: '#ef4444' }, { label: 'Current', data: [impactResults.currentValue], backgroundColor: '#6b7280' }, { label: 'Best Case', data: [impactResults.bestCaseValue], backgroundColor: '#22c55e' } ] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, ticks: { callback: (v) => `$${v.toLocaleString()}` } } }, plugins: { title: { display: true, text: 'Portfolio Value Scenarios' } } } }); }; window.downloadPDF = () => { if (!impactResults) return; const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(20); doc.text("Stock Market Event Impact Report", doc.internal.pageSize.getWidth() / 2, 20, { align: 'center' }); doc.setFontSize(12); doc.text(`Event: ${impactResults.eventName}`, doc.internal.pageSize.getWidth() / 2, 28, { align: 'center' }); const summaryText = ` Current Portfolio Value: $${impactResults.currentValue.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})} Best-Case Scenario (${impactResults.bestCase}%): $${impactResults.bestCaseValue.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})} (Potential Gain: $${impactResults.bestCaseImpact.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}) Worst-Case Scenario (${impactResults.worstCase}%): $${impactResults.worstCaseValue.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})} (Potential Loss: $${impactResults.worstCaseImpact.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}) `; doc.text(summaryText, 14, 40); const finalY = impactChart ? 90 : 80; if(impactChart) { const chartImage = impactChart.toBase64Image(); doc.addImage(chartImage, 'PNG', 14, finalY, 180, 90); } const head = [['Ticker', 'Current Value ($)', 'Worst-Case Impact ($)', 'Best-Case Impact ($)']]; const body = impactResults.details.map(d => [ d.ticker, d.currentValue.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}), d.worstCaseImpact.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}), d.bestCaseImpact.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}) ]); doc.autoTable({ startY: finalY + (impactChart ? 100 : 10), head: head, body: body, theme: 'striped', headStyles: { fillColor: [37, 99, 235] } }); doc.save('Stock-Impact-Report.pdf'); }; // --- INITIALIZATION --- DOM.nextBtn.addEventListener('click', () => switchTab(currentTab + 1)); DOM.prevBtn.addEventListener('click', () => switchTab(currentTab - 1)); DOM.tabButtons.forEach((btn, i) => btn.addEventListener('click', () => switchTab(i))); renderCurrentTab(); updateNavButtons(); });
Scroll to Top