function fmt(n){ if(Math.abs(n)>=1e6) return '$'+(n/1e6).toFixed(2)+'M'; return '$'+n.toLocaleString('en-US',{minimumFractionDigits:0,maximumFractionDigits:0}); } function calculate(){ var init=parseFloat(document.getElementById('initialInvestment').value)||0; var monthly=parseFloat(document.getElementById('monthlyContribution').value)||0; var years=parseInt(document.getElementById('holdingYears').value)||1; var yieldPct=(parseFloat(document.getElementById('dividendYield').value)||0)/100; var divGrowth=(parseFloat(document.getElementById('dividendGrowth').value)||0)/100; var priceGr=(parseFloat(document.getElementById('priceGrowth').value)||0)/100; var drip=document.getElementById('drip').checked; if(years<1) years=1; if(years>50) years=50; var annualContrib=monthly*12; var dripVal=init,dripCumDiv=0,noDripVal=init,noDripCumDiv=0,rows=[]; for(var y=1;y<=years;y++){ var totalContributed=init+annualContrib*y; var effYield=yieldPct*Math.pow(1+divGrowth,y-1); var dripStartVal=dripVal; var dripEndPreDiv=dripStartVal*(1+priceGr)+annualContrib*(1+priceGr*0.5); var dripAvgVal=(dripStartVal+dripEndPreDiv)/2; var dripAnnualDiv=Math.max(0,effYield*dripAvgVal);dripCumDiv+=dripAnnualDiv;dripVal=dripEndPreDiv+dripAnnualDiv; var noDripStartVal=noDripVal; var noDripEndPreDiv=noDripStartVal*(1+priceGr)+annualContrib*(1+priceGr*0.5); var noDripAvgVal=(noDripStartVal+noDripEndPreDiv)/2; var noDripAnnualDiv=Math.max(0,effYield*noDripAvgVal);noDripCumDiv+=noDripAnnualDiv;noDripVal=noDripEndPreDiv; rows.push({year:y,totalContrib:totalContributed,dripEnd:dripVal,noDripEnd:noDripVal,annDiv:drip?dripAnnualDiv:noDripAnnualDiv,cumDiv:drip?dripCumDiv:noDripCumDiv,diff:dripVal-(noDripVal+noDripCumDiv)}); } var last=rows[rows.length-1]; document.getElementById('sumPortfolio').textContent=fmt(drip?last.dripEnd:last.noDripEnd); document.getElementById('sumDividends').textContent=fmt(last.cumDiv); document.getElementById('sumDripDiff').textContent=fmt(last.diff); var tbody=document.getElementById('resultsBody');tbody.innerHTML=''; rows.forEach(function(r){var tr=document.createElement('tr');tr.innerHTML='