{"id":219,"date":"2025-09-10T16:40:36","date_gmt":"2025-09-10T16:40:36","guid":{"rendered":"https:\/\/millionpathapp.com\/?page_id=219"},"modified":"2025-09-10T16:40:36","modified_gmt":"2025-09-10T16:40:36","slug":"%f0%9f%92%b9-compound-growth-calculator","status":"publish","type":"page","link":"https:\/\/millionpathapp.com\/de\/%f0%9f%92%b9-compound-growth-calculator\/","title":{"rendered":"\ud83d\udcb9 Compound Growth Calculator"},"content":{"rendered":"\n<div class=\"mp-cgc\">\n  <h2>\ud83d\udcb9 Compound Growth Calculator<\/h2>\n  <p class=\"sub\">See how your money can grow over time with monthly compounding.<\/p>\n\n  <div class=\"card grid\">\n    <div>\n      <label>Currency<\/label>\n      <select id=\"cgc-currency\">\n        <option value=\"$\">$ \u2013 USD<\/option>\n        <option value=\"\u20ac\">\u20ac \u2013 EUR<\/option>\n        <option value=\"\u00a3\">\u00a3 \u2013 GBP<\/option>\n        <option value=\"\u062f.\u0639\">\u062f.\u0639 \u2013 IQD<\/option>\n        <option value=\"\ufdfc\">\ufdfc \u2013 SAR<\/option>\n      <\/select>\n    <\/div>\n    <div>\n      <label>Initial amount<\/label>\n      <input id=\"cgc-initial\" type=\"number\" min=\"0\" step=\"0.01\" placeholder=\"e.g., 1000\">\n    <\/div>\n    <div>\n      <label>Monthly contribution<\/label>\n      <input id=\"cgc-monthly\" type=\"number\" min=\"0\" step=\"0.01\" placeholder=\"e.g., 200\">\n    <\/div>\n    <div>\n      <label>Annual interest (APR %)<\/label>\n      <input id=\"cgc-rate\" type=\"number\" min=\"0\" step=\"0.01\" placeholder=\"e.g., 12\">\n    <\/div>\n    <div>\n      <label>Years<\/label>\n      <input id=\"cgc-years\" type=\"number\" min=\"1\" step=\"1\" placeholder=\"e.g., 10\">\n    <\/div>\n    <div>\n      <label>Compound frequency<\/label>\n      <select id=\"cgc-freq\">\n        <option value=\"12\">Monthly (12\u00d7)<\/option>\n        <option value=\"4\">Quarterly (4\u00d7)<\/option>\n        <option value=\"1\">Yearly (1\u00d7)<\/option>\n      <\/select>\n    <\/div>\n  <\/div>\n\n  <div class=\"row\">\n    <button class=\"btn primary\" id=\"cgc-run\">Calculate<\/button>\n    <button class=\"btn\" id=\"cgc-reset\">Reset<\/button>\n  <\/div>\n\n  <div class=\"card kpis\">\n    <div class=\"kpi\">\n      <div class=\"label\">Final balance<\/div>\n      <div class=\"value\" id=\"cgc-final\">\u2014<\/div>\n    <\/div>\n    <div class=\"kpi\">\n      <div class=\"label\">Total contributions<\/div>\n      <div class=\"value\" id=\"cgc-contrib\">\u2014<\/div>\n    <\/div>\n    <div class=\"kpi\">\n      <div class=\"label\">Total interest earned<\/div>\n      <div class=\"value\" id=\"cgc-interest\">\u2014<\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"card\">\n    <canvas id=\"cgc-chart\" height=\"240\" aria-label=\"Growth chart\"><\/canvas>\n    <div class=\"legend\">\n      <span class=\"dot base\"><\/span> Contributions\n      <span class=\"dot growth\"><\/span> Balance\n    <\/div>\n  <\/div>\n\n  <details class=\"card\">\n    <summary>Monthly schedule (toggle)<\/summary>\n    <div class=\"table-wrap\">\n      <table class=\"tbl\" id=\"cgc-table\">\n        <thead>\n          <tr>\n            <th>#<\/th><th>Balance<\/th><th>Contribution<\/th><th>Interest<\/th>\n          <\/tr>\n        <\/thead>\n        <tbody><\/tbody>\n      <\/table>\n    <\/div>\n  <\/details>\n<\/div>\n\n<style>\n  .mp-cgc{font-family:system-ui,-apple-system,Segoe UI,Roboto,Inter,Arial,sans-serif;max-width:980px;margin:28px auto;padding:0 16px;color:#0f172a}\n  .mp-cgc h2{margin:0 0 6px;font-size:28px;font-weight:800}\n  .mp-cgc .sub{color:#475569;margin:0 0 14px}\n  .card{background:#fff;border:1px solid #e5e7eb;border-radius:14px;padding:16px;box-shadow:0 6px 20px rgba(15,23,42,.06);margin:14px 0}\n  .grid{display:grid;gap:12px;grid-template-columns:repeat(6,1fr)}\n  .grid>div{display:grid;gap:6px}\n  label{font-size:13px;color:#64748b}\n  input,select{border:1px solid #e5e7eb;border-radius:10px;padding:10px 12px;font-size:15px;background:#fff;color:#0f172a;outline:none}\n  input:focus,select:focus{border-color:#2563eb;box-shadow:0 0 0 3px rgba(37,99,235,.15)}\n  @media(max-width:900px){.grid{grid-template-columns:repeat(2,1fr)}}\n  .row{display:flex;gap:10px;flex-wrap:wrap;margin:10px 0}\n  .btn{border:1px solid #e5e7eb;background:#fff;border-radius:10px;padding:10px 14px;cursor:pointer}\n  .btn.primary{background:linear-gradient(135deg,#2563eb,#1d4ed8);border-color:#1d4ed8;color:#fff;font-weight:600}\n  .kpis{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}\n  @media(max-width:720px){.kpis{grid-template-columns:1fr}}\n  .kpi{background:#f8fafc;border:1px solid #e5e7eb;border-radius:12px;padding:12px}\n  .kpi .label{font-size:12px;color:#64748b}\n  .kpi .value{font-size:20px;font-weight:800;margin-top:4px}\n  .legend{display:flex;gap:14px;align-items:center;margin-top:10px;color:#475569;font-size:13px}\n  .dot{display:inline-block;width:10px;height:10px;border-radius:999px;vertical-align:middle;margin-right:6px}\n  .dot.base{background:#10b981}\n  .dot.growth{background:#2563eb}\n  .table-wrap{overflow:auto}\n  .tbl{width:100%;border-collapse:collapse}\n  .tbl th,.tbl td{border-bottom:1px solid #e5e7eb;padding:8px 10px;text-align:left;white-space:nowrap}\n<\/style>\n\n<script>\n(function(){\n  const $ = s => document.querySelector(s);\n  const fmt = (v,sym) => `${sym? sym+' ':''}${Number(v||0).toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2})}`;\n  const lsKey = 'mp_cgc_inputs_v1';\n\n  const els = {\n    cur:   $('#cgc-currency'),\n    init:  $('#cgc-initial'),\n    mon:   $('#cgc-monthly'),\n    rate:  $('#cgc-rate'),\n    yrs:   $('#cgc-years'),\n    freq:  $('#cgc-freq'),\n    run:   $('#cgc-run'),\n    reset: $('#cgc-reset'),\n    fin:   $('#cgc-final'),\n    con:   $('#cgc-contrib'),\n    int:   $('#cgc-interest'),\n    cvs:   $('#cgc-chart'),\n    tbody: $('#cgc-table tbody')\n  };\n\n  \/\/ Load previous inputs if any\n  try{\n    const saved = JSON.parse(localStorage.getItem(lsKey)||'{}');\n    Object.entries(saved).forEach(([k,v])=>{\n      const el = els[k]; if(el) el.value = v;\n    });\n  }catch(e){}\n\n  \/\/ Core calc\n  function calc(){\n    const sym = els.cur.value || '$';\n    const P0 = +els.init.value || 0;\n    const PM = +els.mon.value || 0;\n    const r  = (+els.rate.value || 0) \/ 100;\n    const n  = +els.freq.value || 12; \/\/ compounding per year\n    const y  = Math.max(1, (+els.yrs.value || 1));\n    const months = Math.round(y*12);\n\n    \/\/ month rate based on chosen compounding (convert APR to per-month effective)\n    const r_eff_month = (Math.pow(1 + r\/n, n\/12) - 1);\n\n    let bal = P0;\n    let totalContrib = P0;\n    const rows = [];\n    const pointsBal = [];\n    const pointsContrib = [];\n\n    for(let m=1; m<=months; m++){\n      \/\/ interest on current balance\n      const interest = bal * r_eff_month;\n      bal += interest;\n      \/\/ contribution at end of month\n      bal += PM;\n      totalContrib += PM;\n      rows.push({m, bal, contrib: PM, interest});\n      \/\/ chart points per quarter to keep it light\n      if(m % Math.max(1, Math.floor(months\/60)) === 0){\n        pointsBal.push(bal);\n        pointsContrib.push(totalContrib);\n      }\n    }\n\n    const totalInterest = bal - totalContrib;\n\n    els.fin.textContent = fmt(bal, sym);\n    els.con.textContent = fmt(totalContrib, sym);\n    els.int.textContent = fmt(totalInterest, sym);\n\n    \/\/ render table (first\/last 12 months for brevity)\n    renderTable(rows, sym);\n\n    \/\/ chart\n    drawChart(els.cvs, pointsContrib, pointsBal, sym);\n  }\n\n  function renderTable(rows, sym){\n    const maxRows = 24;\n    let show = rows;\n    if(rows.length > maxRows){\n      show = rows.slice(0,12).concat([{sep:true}]).concat(rows.slice(-12));\n    }\n    els.tbody.innerHTML = show.map((r,i)=>{\n      if(r.sep) return `<tr><td colspan=\"4\" style=\"color:#64748b\">\u2026<\/td><\/tr>`;\n      return `<tr>\n        <td>${r.m}<\/td>\n        <td>${fmt(r.bal, sym)}<\/td>\n        <td>${fmt(r.contrib, sym)}<\/td>\n        <td>${fmt(r.interest, sym)}<\/td>\n      <\/tr>`;\n    }).join('');\n  }\n\n  function drawChart(canvas, dataA, dataB){\n    const ctx = canvas.getContext('2d');\n    const w = canvas.width = canvas.clientWidth * (window.devicePixelRatio||1);\n    const h = canvas.height = canvas.getAttribute('height') * (window.devicePixelRatio||1);\n    ctx.scale(window.devicePixelRatio||1, window.devicePixelRatio||1);\n    ctx.clearRect(0,0,canvas.clientWidth,canvas.height);\n\n    const pad = 28;\n    const cw = canvas.clientWidth - pad*2;\n    const ch = (canvas.height\/(window.devicePixelRatio||1)) - pad*2;\n\n    const maxY = Math.max(1, ...dataA, ...dataB);\n    const xStep = cw \/ Math.max(1, (dataB.length-1));\n    const y = v => pad + ch - (v\/maxY)*ch;\n    const x = i => pad + i*xStep;\n\n    \/\/ grid\n    const gridLines = 4;\n    ctx.strokeStyle = '#e5e7eb';\n    ctx.lineWidth = 1;\n    for(let g=0; g<=gridLines; g++){\n      const gy = pad + (ch\/gridLines)*g;\n      ctx.beginPath(); ctx.moveTo(pad, gy); ctx.lineTo(pad+cw, gy); ctx.stroke();\n    }\n\n    \/\/ line B (Balance) \u2013 blue\n    ctx.strokeStyle = '#2563eb';\n    ctx.lineWidth = 2;\n    ctx.beginPath();\n    dataB.forEach((v,i)=>{ i? ctx.lineTo(x(i), y(v)) : ctx.moveTo(x(i), y(v)); });\n    ctx.stroke();\n\n    \/\/ line A (Contrib) \u2013 green\n    ctx.strokeStyle = '#10b981';\n    ctx.lineWidth = 2;\n    ctx.beginPath();\n    dataA.forEach((v,i)=>{ i? ctx.lineTo(x(i), y(v)) : ctx.moveTo(x(i), y(v)); });\n    ctx.stroke();\n  }\n\n  \/\/ Events\n  $('#cgc-run').addEventListener('click', ()=>{\n    persistInputs();\n    calc();\n    \/\/ smooth scroll to results on mobile\n    document.querySelector('.kpis').scrollIntoView({behavior:'smooth', block:'center'});\n  });\n  $('#cgc-reset').addEventListener('click', ()=>{\n    ['init','mon','rate','yrs'].forEach(k=> els[k].value='');\n    els.freq.value='12'; calc();\n  });\n\n  \/\/ persist inputs\n  function persistInputs(){\n    const data = {\n      cur: els.cur.value,\n      init: els.init.value,\n      mon: els.mon.value,\n      rate: els.rate.value,\n      yrs: els.yrs.value,\n      freq: els.freq.value\n    };\n    localStorage.setItem(lsKey, JSON.stringify(data));\n  }\n\n  \/\/ First run with defaults if any\n  if(!els.rate.value) els.rate.value = 12;\n  if(!els.yrs.value) els.yrs.value = 10;\n  if(!els.init.value) els.init.value = 1000;\n  if(!els.mon.value) els.mon.value = 200;\n  calc();\n\n  \/\/ Redraw on resize for crisp lines\n  window.addEventListener('resize', ()=> drawChart(els.cvs, [], []));\n})();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-219","page","type-page","status-publish","hentry"],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/pages\/219","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/comments?post=219"}],"version-history":[{"count":1,"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/pages\/219\/revisions"}],"predecessor-version":[{"id":220,"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/pages\/219\/revisions\/220"}],"wp:attachment":[{"href":"https:\/\/millionpathapp.com\/de\/wp-json\/wp\/v2\/media?parent=219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}