Historical Market Cycle Analyzer

Historical Market Cycle Analyzer

Analyze simulated historical market cycles for insights on stock investments. (Example Indices: SP500_SIM, NASDAQ_SIM)

Simulated data not available for selected index.

`; resultsArea.style.display = 'block'; return; } let historicalCycles = indexData.cycles; let periodStartDate; if (analysisPeriod === "5Y") { periodStartDate = { year: SIMULATED_CURRENT_YEAR - 5, month: SIMULATED_CURRENT_MONTH }; } else if (analysisPeriod === "10Y") { periodStartDate = { year: SIMULATED_CURRENT_YEAR - 10, month: SIMULATED_CURRENT_MONTH }; } // "ALL" means no start date filter if (periodStartDate) { historicalCycles = historicalCycles.filter(cycle => { const cycleEndDate = parseDateString(cycle.endDate); // Include cycle if it ends after or on the period start date return cycleEndDate.year > periodStartDate.year || (cycleEndDate.year === periodStartDate.year && cycleEndDate.month >= periodStartDate.month); }); } if (historicalCycles.length === 0) { resultsArea.innerHTML = `

No simulated historical cycles found for the selected period for ${indexData.name}.

`; resultsArea.style.display = 'block'; return; } const tableHtml = historicalCycles.map(cycle => ` ${cycle.phase} ${cycle.startDate} ${cycle.endDate} ${cycle.durationMonths} ${cycle.totalReturn.toFixed(1)}% ${cycle.notes} `).join(''); const timelineHtml = historicalCycles.map(cycle => `
${cycle.phase}
(${cycle.startDate} - ${cycle.endDate})
${cycle.totalReturn.toFixed(1)}%
`).join(''); resultsArea.innerHTML = `

Historical Market Cycle Analysis

Index: ${indexData.name} | Stock Context: ${stockTickerForReport}

Generated: ${new Date().toLocaleString()}

Analysis for ${indexData.name}

(Stock Investment Context: ${stockTickerForReport})

Current Simulated Market Phase: ${indexData.currentPhaseGuess}

${indexData.currentPhaseNotes}

Simulated Historical Cycle Timeline (${analysisPeriod})

${timelineHtml}

Simulated Historical Cycle Details (${analysisPeriod})

${tableHtml}
PhaseStartEndDuration (M)Total Return %Notes

Disclaimer: This analysis uses simulated historical data and predefined cycle interpretations. It is for illustrative educational purposes only and does not constitute financial advice or a guarantee of future market movements.

`; resultsArea.style.display = 'block'; resultsArea.scrollIntoView({ behavior: 'smooth' }); } async function generateCyclePdf() { const pdfContent = document.getElementById('pdf-content'); const downloadBtn = event.target; if (!pdfContent) { console.error("PDF content area not found."); if(typeof alert === 'function') alert("Error: Could not find content to generate PDF."); return; } if (!html2canvas || !jsPDF) { console.error("html2canvas or jsPDF library not found."); if(typeof alert === 'function') alert("Error: PDF generation library not loaded."); return; } const originalButtonText = downloadBtn.textContent; downloadBtn.textContent = "Generating..."; downloadBtn.disabled = true; const pdfHeaderElement = pdfContent.querySelector('.pdf-header'); const screenHeaderElements = pdfContent.querySelectorAll('.screen-only'); if (pdfHeaderElement) pdfHeaderElement.style.display = 'block'; screenHeaderElements.forEach(el => el.style.display = 'none'); try { const canvas = await html2canvas(pdfContent, { scale: 1.5, useCORS: true, logging: false, onclone: (doc) => { const clonedHeader = doc.querySelector('.pdf-header'); if (clonedHeader) clonedHeader.style.display = 'block'; doc.querySelectorAll('.screen-only').forEach(el => el.style.display = 'none'); } }); if (pdfHeaderElement) pdfHeaderElement.style.display = 'none'; screenHeaderElements.forEach(el => el.style.display = 'block'); const imgData = canvas.toDataURL('image/jpeg', 0.8); const pdf = new jsPDF({ orientation: 'p', // Portrait unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgProps = pdf.getImageProperties(imgData); const margin = 10; const contentWidth = pdfWidth - 2 * margin; let contentHeight = (imgProps.height * contentWidth) / imgProps.width; let currentPosition = margin; if (contentHeight <= pdfHeight - 2 * margin) { pdf.addImage(imgData, 'JPEG', margin, currentPosition, contentWidth, contentHeight); } else { // Multi-page logic for tall content let remainingImgHeight = imgProps.height; // Use original image pixel height let sourceY = 0; // Y-offset in the source canvas const sourceWidth = imgProps.width; // Calculate how many pixels from the source canvas fit onto one PDF page height const pageCanvasHeight = ((pdfHeight - 2 * margin) / contentWidth) * sourceWidth; while (remainingImgHeight > 0) { const currentChunkHeight = Math.min(remainingImgHeight, pageCanvasHeight); const tempCanvas = document.createElement('canvas'); tempCanvas.width = sourceWidth; tempCanvas.height = currentChunkHeight; const tempCtx = tempCanvas.getContext('2d'); // Draw the chunk from the original large canvas to the temporary canvas tempCtx.drawImage(canvas, 0, sourceY, sourceWidth, currentChunkHeight, 0, 0, sourceWidth, currentChunkHeight); const chunkImgData = tempCanvas.toDataURL('image/jpeg', 0.8); // Calculate the display height of this chunk in the PDF const chunkDisplayHeight = (currentChunkHeight * contentWidth) / sourceWidth; pdf.addImage(chunkImgData, 'JPEG', margin, currentPosition, contentWidth, chunkDisplayHeight); remainingImgHeight -= currentChunkHeight; sourceY += currentChunkHeight; if (remainingImgHeight > 0) { pdf.addPage(); currentPosition = margin; // Reset Y position for new page } } } const indexName = document.getElementById('marketIndex').value.replace('_SIM', '') || "Market"; pdf.save(`${indexName}_MarketCycle_Analysis.pdf`); } catch (error) { console.error("Error generating PDF:", error); if(typeof alert === 'function') alert("An error occurred while generating the PDF: " + error.message); } finally { downloadBtn.textContent = originalButtonText; downloadBtn.disabled = false; if (pdfHeaderElement) pdfHeaderElement.style.display = 'none'; screenHeaderElements.forEach(el => el.style.display = 'block'); } }
Scroll to Top