Dollar-Cost Averaging Automation Tool

Dollar-Cost Averaging Automation Tool

Dollar-Cost Averaging Simulation Results

No simulation data available. Please calculate results first.

'; simulationTableContainer.style.display = 'none'; downloadPdfButton.style.display = 'none'; // Ensure PDF button is hidden pdfContentArea.innerHTML = ''; // Clear PDF content area return; } const finalPeriod = data[data.length - 1]; const finalPortfolioValue = finalPeriod.portfolioValue; const totalGainLoss = finalPortfolioValue - totalInvested; const roiPercentage = (totalInvested > 0) ? (totalGainLoss / totalInvested) * 100 : 0; const summaryHtml = `
Total Invested: $${totalInvested.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
Final Portfolio Value: $${finalPortfolioValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
Total Gain/Loss: $${totalGainLoss.toLocaleString('en-US', { signDisplay: 'exceptZero', minimumFractionDigits: 2, maximumFractionDigits: 2 })}
Return on Investment (ROI): ${roiPercentage.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}%
Average Price Per Unit (DCA): $${(totalInvested / finalPeriod.totalUnits).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
Final Market Price: $${finalPeriod.marketPrice.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
`; resultsSummaryDiv.innerHTML = summaryHtml; // Populate simulation table for display simulationTableBody.innerHTML = ''; // Clear previous data data.forEach(row => { const tr = document.createElement('tr'); tr.innerHTML = ` ${row.period === 0 ? 'Initial' : row.period} $${row.marketPrice.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${row.unitsPurchased.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 })} ${row.totalUnits.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 })} $${row.totalInvested.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} $${row.portfolioValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} `; simulationTableBody.appendChild(tr); }); simulationTableContainer.style.display = 'block'; // --- Prepare content for PDF --- let pdfTableHtml = ` `; data.forEach((row, index) => { const rowBg = index % 2 === 0 ? '#f9f9f9' : '#fff'; // For zebra striping in PDF table pdfTableHtml += ` `; }); pdfTableHtml += `
Period Market Price ($) Units Purchased Total Units Total Invested ($) Portfolio Value ($)
${row.period === 0 ? 'Initial' : row.period} $${row.marketPrice.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${row.unitsPurchased.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 })} ${row.totalUnits.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 })} $${row.totalInvested.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} $${row.portfolioValue.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
`; pdfContentArea.innerHTML = `

Dollar-Cost Averaging Simulation Results

Summary

${summaryHtml}

Investment Growth Over Time

${pdfTableHtml} `; // End prepare content for PDF downloadPdfButton.style.display = 'block'; } // --- PDF Download Logic --- downloadPdfButton.addEventListener('click', async function() { const { jsPDF } = window.jspdf; const pdf = new jsPDF('p', 'pt', 'letter'); // Ensure the PDF content area is temporarily visible for html2canvas to render it pdfContentArea.style.display = 'block'; await html2canvas(pdfContentArea, { scale: 2, // Higher scale for better quality logging: false, useCORS: true // Essential for images from other origins if any }).then(canvas => { const imgData = canvas.toDataURL('image/png'); const imgWidth = pdf.internal.pageSize.getWidth() - 60; // Page width - 30pt margin on each side const imgHeight = canvas.height * imgWidth / canvas.width; let heightLeft = imgHeight; let position = 30; // Initial Y position for content, respecting margins pdf.addImage(imgData, 'PNG', 30, position, imgWidth, imgHeight); heightLeft -= (pdf.internal.pageSize.getHeight() - 30); // Account for remaining height after first page content while (heightLeft > 0) { position = heightLeft - imgHeight; // Calculate new position for the next page pdf.addPage(); pdf.addImage(imgData, 'PNG', 30, position, imgWidth, imgHeight); heightLeft -= (pdf.internal.pageSize.getHeight() - 30); } pdf.save('dca_results.pdf'); }).catch(error => { console.error("Error generating PDF:", error); alert("Failed to generate PDF. Please try again or check console for errors."); }).finally(() => { // Hide the PDF content area again after processing pdfContentArea.style.display = 'none'; }); }); });
Scroll to Top