Budgeting Tool for Investors (Personal Planning Tool)

This tool helps you manually create and analyze your budget. Data is stored in your browser's local storage. Export your data regularly for backup.

Income Sources

Expenses

Planned Investment Contributions

Budget Summary & Analysis

Budget summary will appear here.

Income Sources

Expense Categories

Investment Allocations

Manage Budget Data

Your budget data is stored in your browser's local storage. Export it regularly for backup or to transfer to another browser/device.

Net Annual Cash Flow: ${bti_formatCurrency(netCashFlowMonthly * 12)}

`; // Render Charts bti_renderPieChart(bti_data.summaryResults.incomeBreakdown.filter(i => i.monthlyAmount > 0).map(i => ({label: i.name, value: i.monthlyAmount})), 'bti_incomePieChartContainer'); bti_renderPieChart(bti_data.summaryResults.expensesByCategory.filter(e => e.monthlyAmount > 0).map(e => ({label: e.name, value: e.monthlyAmount})), 'bti_expensePieChartContainer'); bti_renderPieChart(bti_data.summaryResults.investmentsBreakdown.filter(inv => inv.monthlyAmount > 0).map(inv => ({label: inv.name, value: inv.monthlyAmount})), 'bti_investmentPieChartContainer'); const pdfButton = document.getElementById('bti_downloadPdfButton'); if (pdfButton) pdfButton.style.display = 'block'; } function bti_renderPieChart(data, containerId) { // data = [{label, value}] const container = bti_getEl(containerId); if (!container) return; container.innerHTML = ''; const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute('class', 'bti_pie_chart_svg'); const filteredData = data.filter(d => d.value > 0); if (filteredData.length === 0) { container.innerHTML = '

No data to display for this chart.

'; return; } const boxSize = Math.min(container.offsetWidth || 280, 280); // Use parent width or default svg.setAttribute('viewBox', `0 0 ${boxSize} ${boxSize}`); const radius = boxSize / 2 * 0.8; const cx = boxSize / 2; const cy = boxSize / 2; let cumulativePercent = 0; const totalValue = filteredData.reduce((sum, d) => sum + d.value, 0); filteredData.forEach((d, index) => { const percent = d.value / totalValue; const startAngle = cumulativePercent * 2 * Math.PI - Math.PI / 2; const endAngle = (cumulativePercent + percent) * 2 * Math.PI - Math.PI / 2; const x1 = cx + radius * Math.cos(startAngle); const y1 = cy + radius * Math.sin(startAngle); const x2 = cx + radius * Math.cos(endAngle); const y2 = cy + radius * Math.sin(endAngle); const largeArcFlag = percent > 0.5 ? 1 : 0; const pathData = `M ${cx},${cy} L ${x1},${y1} A ${radius},${radius} 0 ${largeArcFlag},1 ${x2},${y2} Z`; const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute("d", pathData); path.setAttribute("fill", bti_defaultColors[index % bti_defaultColors.length]); path.setAttribute("stroke", "#F9FAFB"); path.setAttribute("stroke-width", "1"); const title = document.createElementNS("http://www.w3.org/2000/svg", "title"); title.textContent = `${d.label}: ${bti_formatCurrency(d.value)} (${(percent*100).toFixed(1)}%)`; path.appendChild(title); svg.appendChild(path); cumulativePercent += percent; }); container.appendChild(svg); } // --- Tab 5: Manage Data --- function bti_exportData() { /* Same as hfit_exportData, adapted for bti_data */ const jsonData = JSON.stringify(bti_data, null, 2); const blob = new Blob([jsonData], {type: 'application/json'}); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'bti_investor_budget_data.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); alert("Budget data exported successfully!"); } function bti_importData(event) { /* Same as hfit_importData, adapted for bti_data */ const file = event.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = function(e) { try { const importedData = JSON.parse(e.target.result); if (importedData && importedData.incomes && importedData.expenses && importedData.investments) { if (confirm("Importing will overwrite current budget data. Are you sure?")) { bti_data = importedData; bti_saveData(); alert("Data imported successfully! Refreshing lists and summary..."); bti_renderAllLists(); bti_calculateAndDisplaySummary(); } } else { alert("Invalid file format for budget data."); } } catch (err) { alert("Error importing file: " + err.message); } }; reader.readAsText(file); event.target.value = ''; } } function bti_clearAllData() { /* Same as hfit_clearAllData, adapted for bti_data */ if (confirm("Are you sure you want to clear ALL locally stored budget data? This action cannot be undone.")) { bti_data = { incomes: [], expenses: [], investments: [] }; bti_saveData(); alert("All budget data cleared."); bti_renderAllLists(); bti_calculateAndDisplaySummary(); } } // --- PDF Generation --- function bti_downloadPDF() { if (!bti_data.summaryResults) { alert("Please calculate summary first."); return; } if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { alert('Core PDF library (jsPDF) is not loaded.'); return; } const { jsPDF: JSPDF } = window.jspdf; const doc = new JSPDF(); if (typeof doc.autoTable !== 'function') { alert('PDF Table plugin (jsPDF-AutoTable) not loaded. PDF formatting may be basic.'); } let y = 15; const m = 15; const s = bti_data.summaryResults; doc.setFontSize(16); doc.text("Investor Budget Report", m, y); y += 10; doc.setFontSize(10); doc.text(`Report Date: ${new Date().toLocaleDateString()}`, m, y); y += 7; doc.setFontSize(12); doc.text("Monthly Budget Summary:", m, y); y += 6; let summaryData = [ ["Total Monthly Income:", bti_formatCurrency(s.totalMonthlyIncome)], ["Total Monthly Expenses:", bti_formatCurrency(s.totalMonthlyExpenses)], ["Total Monthly Investments:", bti_formatCurrency(s.totalMonthlyInvestments)], [{content: "Net Monthly Cash Flow:", styles:{fontStyle:'bold'}}, {content: bti_formatCurrency(s.netCashFlowMonthly), styles:{fontStyle:'bold', textColor: s.netCashFlowMonthly >=0 ? [22,163,74] : [220,38,38]}}], ["Investment Savings Rate:", bti_formatPercent(s.savingsRate)], ["Disposable Savings Rate:", bti_formatPercent(s.disposableSavingsRate)], ]; if (typeof doc.autoTable === 'function') { doc.autoTable({startY: y, body: summaryData, theme: 'plain', styles:{fontSize:9, cellPadding:1.2}, columnStyles:{0:{fontStyle:'bold'}}}); y = doc.lastAutoTable.finalY + 5; } else { summaryData.forEach(row => {doc.text(`${row[0]} ${row[1]}`,m,y); y+=4;}); y+=3;} const makeTable = (title, items) => { if (items.length === 0) return; if (y > 240 && items.length > 3) { doc.addPage(); y = m;} doc.setFontSize(11); doc.text(title, m, y); y += 5; const head = [['Source/Item', 'Monthly Amount ($)', 'Frequency']]; const body = items.map(item => [ item.name || item.itemName || 'Unnamed', bti_formatCurrency(bti_calculateMonthlyValue(item.amount || item.contributionAmount, item.frequency)), item.frequency.charAt(0).toUpperCase() + item.frequency.slice(1) ]); if (typeof doc.autoTable === 'function') { doc.autoTable({startY: y, head: head, body: body, theme: 'striped', headStyles:{fillColor:[30,64,175]}, styles:{fontSize:8}}); y = doc.lastAutoTable.finalY + 6; } else { body.forEach(row => {doc.text(row.join(' | '), m+5, y); y+=3.5;}); y+=3;} }; makeTable("Income Sources (Monthly Equivalent):", bti_data.incomes); makeTable("Expense Breakdown (Monthly Equivalent):", bti_data.expenses.map(e => ({...e, name: `${e.category}: ${e.itemName}`}))); // Combine cat & item makeTable("Planned Investments (Monthly Equivalent):", bti_data.investments); if (y > 275) { doc.addPage(); y = m; } doc.setFontSize(8); doc.text("Note: This is a conceptual budgeting tool based on user-defined inputs. For informational purposes only.", m, y); doc.save('Investor_Budget_Report.pdf'); }
Scroll to Top