{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# 📘 Fincept Notebook — Inflation & Real Returns\n",
        "\n",
        "**Economics · Beginner · ~12 min · Standard library only**\n",
        "\n",
        "Inflation quietly erodes the value of money. This notebook starts from a Consumer Price Index (CPI) series, derives year-over-year inflation, converts nominal investment returns into real (inflation-adjusted) returns using the Fisher relation, shows how the purchasing power of idle cash decays, and uses the Rule of 72 to estimate doubling times.\n",
        "\n",
        "**What you'll learn**\n",
        "- How to compute year-over-year inflation from a CPI index\n",
        "- The Fisher relation: turning nominal returns into real returns\n",
        "- How inflation erodes the purchasing power of cash over time\n",
        "- The Rule of 72 for estimating doubling (and halving) times\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 1. CPI index and year-over-year inflation\n",
        "\n",
        "A **CPI** is an index that tracks the average price level of a basket of goods, anchored to a base year. The **year-over-year inflation rate** between two years is simply the percentage change in the index:\n",
        "\n",
        "`inflation_t = CPI_t / CPI_{t-1} − 1`\n",
        "\n",
        "Below is an embedded annual CPI series; we compute the inflation rate for each year.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "fincept_title": "CPI & inflation"
      },
      "outputs": [],
      "source": [
        "# Annual end-of-year CPI index (illustrative, base = 100.0 in the first year)\n",
        "cpi = {\n",
        "    2015: 100.0,\n",
        "    2016: 101.3,\n",
        "    2017: 103.4,\n",
        "    2018: 105.9,\n",
        "    2019: 107.8,\n",
        "    2020: 109.2,\n",
        "    2021: 114.4,\n",
        "    2022: 123.6,\n",
        "    2023: 128.7,\n",
        "    2024: 132.6,\n",
        "}\n",
        "\n",
        "years = sorted(cpi)\n",
        "print(\"Year-over-year inflation from the CPI series:\")\n",
        "print(f\"{'Year':>6}{'CPI':>10}{'Inflation':>12}\")\n",
        "print('-' * 28)\n",
        "inflation = {}\n",
        "for prev, cur in zip(years, years[1:]):\n",
        "    rate = cpi[cur] / cpi[prev] - 1\n",
        "    inflation[cur] = rate\n",
        "    print(f\"{cur:>6}{cpi[cur]:>10.1f}{rate:>11.2%}\")\n",
        "\n",
        "# Average (compound annual) inflation over the whole span\n",
        "n = years[-1] - years[0]\n",
        "cagr = (cpi[years[-1]] / cpi[years[0]]) ** (1 / n) - 1\n",
        "print('-' * 28)\n",
        "print(f\"\\nCumulative price rise {years[0]}-{years[-1]}: {cpi[years[-1]] / cpi[years[0]] - 1:.1%}\")\n",
        "print(f\"Average annual inflation (CAGR): {cagr:.2%}\")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 2. Nominal vs real returns (the Fisher relation)\n",
        "\n",
        "A **nominal** return is the headline percentage your money grew. The **real** return strips out inflation to show the gain in actual purchasing power. The exact Fisher relation is:\n",
        "\n",
        "`1 + real = (1 + nominal) / (1 + inflation)`  →  `real = (1 + nominal) / (1 + inflation) − 1`\n",
        "\n",
        "A common shortcut, `real ≈ nominal − inflation`, is close but slightly overstates the real return; we show both.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "fincept_title": "Real returns"
      },
      "outputs": [],
      "source": [
        "def real_return(nominal, inflation):\n",
        "    \"\"\"Exact Fisher relation: real return given a nominal return and inflation.\"\"\"\n",
        "    return (1 + nominal) / (1 + inflation) - 1\n",
        "\n",
        "# A few investments and the inflation backdrop each faced\n",
        "scenarios = [\n",
        "    ('Savings account',  0.015, 0.032),\n",
        "    ('Government bond',   0.035, 0.032),\n",
        "    ('Balanced fund',     0.070, 0.045),\n",
        "    ('Equity portfolio',  0.110, 0.045),\n",
        "    ('High-inflation yr', 0.080, 0.090),\n",
        "]\n",
        "\n",
        "print(\"Nominal vs real returns (exact Fisher relation):\")\n",
        "print(f\"{'Asset':<20}{'Nominal':>10}{'Inflation':>11}{'Real (exact)':>14}{'Approx':>9}\")\n",
        "print('-' * 64)\n",
        "for name, nom, infl in scenarios:\n",
        "    real = real_return(nom, infl)\n",
        "    approx = nom - infl\n",
        "    print(f\"{name:<20}{nom:>10.2%}{infl:>11.2%}{real:>14.2%}{approx:>9.2%}\")\n",
        "\n",
        "print(\"\\nNote: when nominal return < inflation, the real return is negative —\")\n",
        "print(\"your money grows in dollars but buys less than before.\")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 3. Purchasing power erosion of cash\n",
        "\n",
        "Cash earning nothing loses real value every year inflation is positive. If you hold a fixed amount of money, its purchasing power in base-year terms is:\n",
        "\n",
        "`real value_t = nominal amount × CPI_base / CPI_t`\n",
        "\n",
        "We track $10,000 of idle cash across the same CPI series to see how much buying power it quietly loses.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "fincept_title": "Purchasing power"
      },
      "outputs": [],
      "source": [
        "cpi = {\n",
        "    2015: 100.0, 2016: 101.3, 2017: 103.4, 2018: 105.9, 2019: 107.8,\n",
        "    2020: 109.2, 2021: 114.4, 2022: 123.6, 2023: 128.7, 2024: 132.6,\n",
        "}\n",
        "\n",
        "years = sorted(cpi)\n",
        "base = years[0]\n",
        "cash = 10000.0\n",
        "\n",
        "print(f\"Purchasing power of ${cash:,.0f} held as idle cash (in {base} dollars):\")\n",
        "print(f\"{'Year':>6}{'CPI':>10}{'Real value':>14}{'Buying power lost':>20}\")\n",
        "print('-' * 50)\n",
        "for y in years:\n",
        "    real_value = cash * cpi[base] / cpi[y]\n",
        "    lost = cash - real_value\n",
        "    print(f\"{y:>6}{cpi[y]:>10.1f}{real_value:>14,.2f}{lost:>20,.2f}\")\n",
        "\n",
        "final_real = cash * cpi[base] / cpi[years[-1]]\n",
        "print('-' * 50)\n",
        "print(f\"\\nOver {years[-1] - base} years, ${cash:,.0f} of cash kept only \"\n",
        "      f\"${final_real:,.2f} of {base} purchasing power\")\n",
        "print(f\"— a real loss of {(1 - final_real / cash):.1%}.\")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 4. The Rule of 72\n",
        "\n",
        "The **Rule of 72** is a quick mental estimate: divide 72 by a percentage growth rate to approximate the years needed to double. It also works in reverse for inflation — dividing 72 by the inflation rate estimates how long until money's purchasing power halves. We compare the rule against the exact logarithmic answer.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "fincept_title": "Rule of 72"
      },
      "outputs": [],
      "source": [
        "import math\n",
        "\n",
        "def rule_of_72(rate_pct):\n",
        "    return 72 / rate_pct\n",
        "\n",
        "def exact_doubling(rate_pct):\n",
        "    return math.log(2) / math.log(1 + rate_pct / 100)\n",
        "\n",
        "print(\"Doubling time: Rule of 72 vs exact\")\n",
        "print(f\"{'Rate':>6}{'Rule of 72':>14}{'Exact (yrs)':>14}{'Error':>10}\")\n",
        "print('-' * 44)\n",
        "for rate in [2, 3, 4, 6, 8, 10, 12]:\n",
        "    approx = rule_of_72(rate)\n",
        "    exact = exact_doubling(rate)\n",
        "    print(f\"{rate:>5}%{approx:>14.1f}{exact:>14.1f}{approx - exact:>+10.2f}\")\n",
        "\n",
        "# Applied to inflation: how fast does purchasing power halve?\n",
        "print(\"\\nApplied to inflation — years for prices to double / money to halve:\")\n",
        "print(f\"{'Inflation':>10}{'Rule of 72':>14}{'Exact (yrs)':>14}\")\n",
        "print('-' * 38)\n",
        "for infl in [2, 3, 5, 7]:\n",
        "    print(f\"{infl:>9}%{rule_of_72(infl):>14.1f}{exact_doubling(infl):>14.1f}\")\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "---\n",
        "*— Fincept Notebook · part of Fincept Terminal. Edit any cell and press Ctrl+Enter to run.*\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
