From 3c960e3ae5b08f08a0ec09d0cb42b28ba5c6090d Mon Sep 17 00:00:00 2001 From: David Trimmer Date: Thu, 19 Mar 2026 17:08:51 -0400 Subject: [PATCH] Add Searchlight Institute tax reform analysis notebooks Three reform variants analyzing CTC and EITC changes: - Reform 1: CTC $3,600-$4,440 (2026-2035) - Reform 2: CTC $3,000-$3,600 (2026-2035) - Reform 3: CTC $2,700-$3,300 (2026-2035) Each notebook includes: - Comprehensive 2026 impact analysis (poverty, deciles, winners/losers) - 10-year federal budgetary projections - CSV exports for both 2026 impacts and 10-year projections Closes #125 Co-Authored-By: Claude Opus 4.5 --- .../reform_1_10year_budgetary_impact.csv | 11 + .../reform_1_analysis.ipynb | 2648 ++++++++++++++++ .../reform_1_impact_2026.csv | 67 + .../reform_2_10year_budgetary_impact.csv | 11 + .../reform_2_analysis.ipynb | 2752 ++++++++++++++++ .../reform_2_impact_2026.csv | 67 + .../reform_3_10year_budgetary_impact.csv | 11 + .../reform_3_analysis.ipynb | 2768 +++++++++++++++++ .../reform_3_impact_2026.csv | 67 + 9 files changed, 8402 insertions(+) create mode 100644 us/searchlight_institute/reform_1_10year_budgetary_impact.csv create mode 100644 us/searchlight_institute/reform_1_analysis.ipynb create mode 100644 us/searchlight_institute/reform_1_impact_2026.csv create mode 100644 us/searchlight_institute/reform_2_10year_budgetary_impact.csv create mode 100644 us/searchlight_institute/reform_2_analysis.ipynb create mode 100644 us/searchlight_institute/reform_2_impact_2026.csv create mode 100644 us/searchlight_institute/reform_3_10year_budgetary_impact.csv create mode 100644 us/searchlight_institute/reform_3_analysis.ipynb create mode 100644 us/searchlight_institute/reform_3_impact_2026.csv diff --git a/us/searchlight_institute/reform_1_10year_budgetary_impact.csv b/us/searchlight_institute/reform_1_10year_budgetary_impact.csv new file mode 100644 index 0000000..a377871 --- /dev/null +++ b/us/searchlight_institute/reform_1_10year_budgetary_impact.csv @@ -0,0 +1,11 @@ +Year,Budgetary Impact +2026,-154164001783.69482 +2027,-157864084761.3623 +2028,-164597276521.37793 +2029,-167287528290.4707 +2030,-175556385052.03516 +2031,-169573356121.84375 +2032,-176599302199.34863 +2033,-178463440201.4834 +2034,-177017552448.71387 +2035,-180123710118.63232 diff --git a/us/searchlight_institute/reform_1_analysis.ipynb b/us/searchlight_institute/reform_1_analysis.ipynb new file mode 100644 index 0000000..376a558 --- /dev/null +++ b/us/searchlight_institute/reform_1_analysis.ipynb @@ -0,0 +1,2648 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Searchlight Institute Tax Reform Analysis\n", + "\n", + "This notebook analyzes the comprehensive impact of the Searchlight Institute tax reform proposal:\n", + "- Full aggregate impacts for 2026 (deciles, poverty, winners/losers, income brackets)\n", + "- 10-year federal budgetary impact (2026-2035)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np\n", + "import plotly.graph_objects as go\n", + "from policyengine_core.charts import format_fig\n", + "import csv" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Searchlight Institute Tax Reform\n", + "# - AFA CTC reforms\n", + "# - EITC eligibility and amount changes\n", + "# - EITC joint bonus set equal to phase-out start values\n", + "\n", + "REFORM_DICT = {\n", + " \"gov.contrib.congress.afa.in_effect\": {\n", + " \"2026-01-01.2100-12-31\": True\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.amount.base\": {\n", + " \"2026-01-01.2026-12-31\": 3600,\n", + " \"2027-01-01.2027-12-31\": 3720,\n", + " \"2028-01-01.2028-12-31\": 3840,\n", + " \"2029-01-01.2029-12-31\": 3960,\n", + " \"2030-01-01.2031-12-31\": 4080,\n", + " \"2032-01-01.2032-12-31\": 4200,\n", + " \"2033-01-01.2034-12-31\": 4320,\n", + " \"2035-01-01.2035-12-31\": 4440\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.max\": {\n", + " \"2026-01-01.2100-12-31\": 200\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.min\": {\n", + " \"2026-01-01.2100-12-31\": 19\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.min_student\": {\n", + " \"2026-01-01.2100-12-31\": 24\n", + " },\n", + " \"gov.irs.credits.eitc.max[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 1502,\n", + " \"2027-01-01.2027-12-31\": 1577,\n", + " \"2028-01-01.2028-12-31\": 1610,\n", + " \"2029-01-01.2029-12-31\": 1645,\n", + " \"2030-01-01.2030-12-31\": 1678,\n", + " \"2031-01-01.2031-12-31\": 1712,\n", + " \"2032-01-01.2032-12-31\": 1746,\n", + " \"2033-01-01.2033-12-31\": 1779,\n", + " \"2034-01-01.2034-12-31\": 1815,\n", + " \"2035-01-01.2035-12-31\": 1851\n", + " },\n", + " \"gov.irs.credits.eitc.phase_in_rate[0].amount\": {\n", + " \"2026-01-01.2100-12-31\": 0.153\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.rate[0].amount\": {\n", + " \"2026-01-01.2100-12-31\": 0.153\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.start[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 11610,\n", + " \"2027-01-01.2027-12-31\": 12190,\n", + " \"2028-01-01.2028-12-31\": 12440,\n", + " \"2029-01-01.2029-12-31\": 12710,\n", + " \"2030-01-01.2030-12-31\": 12970,\n", + " \"2031-01-01.2031-12-31\": 13230,\n", + " \"2032-01-01.2032-12-31\": 13490,\n", + " \"2033-01-01.2033-12-31\": 13750,\n", + " \"2034-01-01.2034-12-31\": 14030,\n", + " \"2035-01-01.2035-12-31\": 14300\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.joint_bonus[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 11610,\n", + " \"2027-01-01.2027-12-31\": 12190,\n", + " \"2028-01-01.2028-12-31\": 12440,\n", + " \"2029-01-01.2029-12-31\": 12710,\n", + " \"2030-01-01.2030-12-31\": 12970,\n", + " \"2031-01-01.2031-12-31\": 13230,\n", + " \"2032-01-01.2032-12-31\": 13490,\n", + " \"2033-01-01.2033-12-31\": 13750,\n", + " \"2034-01-01.2034-12-31\": 14030,\n", + " \"2035-01-01.2035-12-31\": 14300\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.JOINT\": {\n", + " \"2026-01-01.2026-12-31\": 150000,\n", + " \"2027-01-01.2028-12-31\": 155000,\n", + " \"2029-01-01.2029-12-31\": 160000,\n", + " \"2030-01-01.2031-12-31\": 165000,\n", + " \"2032-01-01.2033-12-31\": 170000,\n", + " \"2034-01-01.2034-12-31\": 175000,\n", + " \"2035-01-01.2035-12-31\": 180000\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.SINGLE\": {\n", + " \"2026-01-01.2027-12-31\": 112500,\n", + " \"2028-01-01.2029-12-31\": 117500,\n", + " \"2030-01-01.2031-12-31\": 122500,\n", + " \"2032-01-01.2033-12-31\": 127500,\n", + " \"2034-01-01.2035-12-31\": 132500\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.SURVIVING_SPOUSE\": {\n", + " \"2026-01-01.2026-12-31\": 150000,\n", + " \"2027-01-01.2028-12-31\": 155000,\n", + " \"2029-01-01.2029-12-31\": 160000,\n", + " \"2030-01-01.2031-12-31\": 165000,\n", + " \"2032-01-01.2033-12-31\": 170000,\n", + " \"2034-01-01.2034-12-31\": 175000,\n", + " \"2035-01-01.2035-12-31\": 180000\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.HEAD_OF_HOUSEHOLD\": {\n", + " \"2026-01-01.2027-12-31\": 112500,\n", + " \"2028-01-01.2029-12-31\": 117500,\n", + " \"2030-01-01.2031-12-31\": 122500,\n", + " \"2032-01-01.2033-12-31\": 127500,\n", + " \"2034-01-01.2035-12-31\": 132500\n", + " }\n", + "}\n", + "\n", + "searchlight_reform = Reform.from_dict(REFORM_DICT, country_id=\"us\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comprehensive 2026 Impact Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Intra-decile bounds and labels\n", + "_INTRA_BOUNDS = [-np.inf, -0.05, -1e-3, 1e-3, 0.05, np.inf]\n", + "_INTRA_LABELS = [\n", + " \"Lose more than 5%\",\n", + " \"Lose less than 5%\",\n", + " \"No change\",\n", + " \"Gain less than 5%\",\n", + " \"Gain more than 5%\",\n", + "]\n", + "\n", + "DATASET = \"hf://policyengine/policyengine-us-data/enhanced_cps_2024.h5\"\n", + "\n", + "\n", + "def _poverty_metrics(baseline_rate, reform_rate):\n", + " \"\"\"Return rate change and percent change for a poverty metric.\"\"\"\n", + " rate_change = reform_rate - baseline_rate\n", + " percent_change = (\n", + " rate_change / baseline_rate * 100\n", + " if baseline_rate > 0\n", + " else 0.0\n", + " )\n", + " return rate_change, percent_change\n", + "\n", + "\n", + "def calculate_aggregate_impact(reform, year: int = 2026) -> dict:\n", + " sim_baseline = Microsimulation(dataset=DATASET)\n", + " sim_reform = Microsimulation(reform=reform, dataset=DATASET)\n", + "\n", + " # ===== FISCAL IMPACT =====\n", + " tax_baseline = sim_baseline.calculate(\n", + " \"income_tax\", period=year, map_to=\"household\"\n", + " )\n", + " tax_reform = sim_reform.calculate(\n", + " \"income_tax\", period=year, map_to=\"household\"\n", + " )\n", + " income_change = tax_baseline - tax_reform\n", + " tax_revenue_impact = float(-income_change.sum())\n", + "\n", + " # Total households\n", + " total_households = float((income_change * 0 + 1).sum())\n", + "\n", + " # ===== WINNERS / LOSERS =====\n", + " winners = float((income_change > 1).sum())\n", + " losers = float((income_change < -1).sum())\n", + " beneficiaries = float((income_change > 0).sum())\n", + "\n", + " affected = abs(income_change) > 1\n", + " affected_count = float(affected.sum())\n", + "\n", + " household_weight_early = sim_reform.calculate(\n", + " \"household_weight\", period=year\n", + " )\n", + " affected_mask = np.array(affected).astype(bool)\n", + " change_arr_early = np.array(income_change)\n", + " weight_arr_early = np.array(household_weight_early)\n", + " avg_benefit = (\n", + " float(np.average(\n", + " change_arr_early[affected_mask],\n", + " weights=weight_arr_early[affected_mask],\n", + " ))\n", + " if affected_count > 0\n", + " else 0.0\n", + " )\n", + "\n", + " winners_rate = winners / total_households * 100\n", + " losers_rate = losers / total_households * 100\n", + "\n", + " # ===== INCOME DECILE ANALYSIS =====\n", + " decile = sim_baseline.calculate(\n", + " \"household_income_decile\", period=year, map_to=\"household\"\n", + " )\n", + " baseline_net_income = sim_baseline.calculate(\n", + " \"household_net_income\", period=year, map_to=\"household\"\n", + " )\n", + "\n", + " decile_average = {}\n", + " decile_relative = {}\n", + " for d in range(1, 11):\n", + " dmask = decile == d\n", + " d_count = float(dmask.sum())\n", + " if d_count > 0:\n", + " d_change_sum = float(income_change[dmask].sum())\n", + " decile_average[str(d)] = d_change_sum / d_count\n", + " d_baseline_sum = float(baseline_net_income[dmask].sum())\n", + " decile_relative[str(d)] = (\n", + " d_change_sum / d_baseline_sum\n", + " if d_baseline_sum != 0\n", + " else 0.0\n", + " )\n", + " else:\n", + " decile_average[str(d)] = 0.0\n", + " decile_relative[str(d)] = 0.0\n", + "\n", + " # Intra-decile\n", + " household_weight = sim_reform.calculate(\n", + " \"household_weight\", period=year\n", + " )\n", + " people_per_hh = sim_baseline.calculate(\n", + " \"household_count_people\", period=year, map_to=\"household\"\n", + " )\n", + " capped_baseline = np.maximum(np.array(baseline_net_income), 1)\n", + " rel_change_arr = np.array(income_change) / capped_baseline\n", + "\n", + " decile_arr = np.array(decile)\n", + " weight_arr = np.array(household_weight)\n", + " people_weighted = np.array(people_per_hh) * weight_arr\n", + "\n", + " intra_decile_deciles = {label: [] for label in _INTRA_LABELS}\n", + " for d in range(1, 11):\n", + " dmask = decile_arr == d\n", + " d_people = people_weighted[dmask]\n", + " d_total_people = d_people.sum()\n", + " d_rel = rel_change_arr[dmask]\n", + "\n", + " for lower, upper, label in zip(\n", + " _INTRA_BOUNDS[:-1], _INTRA_BOUNDS[1:], _INTRA_LABELS\n", + " ):\n", + " in_group = (d_rel > lower) & (d_rel <= upper)\n", + " proportion = (\n", + " float(d_people[in_group].sum() / d_total_people)\n", + " if d_total_people > 0\n", + " else 0.0\n", + " )\n", + " intra_decile_deciles[label].append(proportion)\n", + "\n", + " intra_decile_all = {\n", + " label: sum(intra_decile_deciles[label]) / 10\n", + " for label in _INTRA_LABELS\n", + " }\n", + "\n", + " # ===== POVERTY IMPACT =====\n", + " pov_bl = sim_baseline.calculate(\n", + " \"in_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " pov_rf = sim_reform.calculate(\n", + " \"in_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " poverty_baseline_rate = float(pov_bl.mean() * 100)\n", + " poverty_reform_rate = float(pov_rf.mean() * 100)\n", + " poverty_rate_change, poverty_percent_change = _poverty_metrics(\n", + " poverty_baseline_rate, poverty_reform_rate\n", + " )\n", + "\n", + " # Child/deep poverty\n", + " age_arr = np.array(sim_baseline.calculate(\"age\", period=year))\n", + " is_child = age_arr < 18\n", + " pw_arr = np.array(sim_baseline.calculate(\"person_weight\", period=year))\n", + " child_w = pw_arr[is_child]\n", + " total_child_w = child_w.sum()\n", + "\n", + " pov_bl_arr = np.array(pov_bl).astype(bool)\n", + " pov_rf_arr = np.array(pov_rf).astype(bool)\n", + "\n", + " def _child_rate(arr):\n", + " return float(\n", + " (arr[is_child] * child_w).sum() / total_child_w * 100\n", + " ) if total_child_w > 0 else 0.0\n", + "\n", + " child_poverty_baseline_rate = _child_rate(pov_bl_arr)\n", + " child_poverty_reform_rate = _child_rate(pov_rf_arr)\n", + " child_poverty_rate_change, child_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " child_poverty_baseline_rate, child_poverty_reform_rate\n", + " )\n", + " )\n", + "\n", + " deep_bl = sim_baseline.calculate(\n", + " \"in_deep_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " deep_rf = sim_reform.calculate(\n", + " \"in_deep_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " deep_poverty_baseline_rate = float(deep_bl.mean() * 100)\n", + " deep_poverty_reform_rate = float(deep_rf.mean() * 100)\n", + " deep_poverty_rate_change, deep_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " deep_poverty_baseline_rate, deep_poverty_reform_rate\n", + " )\n", + " )\n", + "\n", + " deep_bl_arr = np.array(deep_bl).astype(bool)\n", + " deep_rf_arr = np.array(deep_rf).astype(bool)\n", + " deep_child_poverty_baseline_rate = _child_rate(deep_bl_arr)\n", + " deep_child_poverty_reform_rate = _child_rate(deep_rf_arr)\n", + " deep_child_poverty_rate_change, deep_child_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " deep_child_poverty_baseline_rate,\n", + " deep_child_poverty_reform_rate,\n", + " )\n", + " )\n", + "\n", + " # ===== INCOME BRACKET BREAKDOWN =====\n", + " agi = sim_reform.calculate(\n", + " \"adjusted_gross_income\", period=year, map_to=\"household\"\n", + " )\n", + " agi_arr = np.array(agi)\n", + " change_arr = np.array(income_change)\n", + " affected_mask = np.abs(change_arr) > 1\n", + "\n", + " income_brackets = [\n", + " (0, 50_000, \"Under $50k\"),\n", + " (50_000, 100_000, \"$50k-$100k\"),\n", + " (100_000, 200_000, \"$100k-$200k\"),\n", + " (200_000, 500_000, \"$200k-$500k\"),\n", + " (500_000, 1_000_000, \"$500k-$1M\"),\n", + " (1_000_000, 2_000_000, \"$1M-$2M\"),\n", + " (2_000_000, float(\"inf\"), \"Over $2M\"),\n", + " ]\n", + "\n", + " by_income_bracket = []\n", + " for min_inc, max_inc, label in income_brackets:\n", + " mask = (\n", + " (agi_arr >= min_inc)\n", + " & (agi_arr < max_inc)\n", + " & affected_mask\n", + " )\n", + " bracket_affected = float(weight_arr[mask].sum())\n", + " if bracket_affected > 0:\n", + " bracket_cost = float(\n", + " (change_arr[mask] * weight_arr[mask]).sum()\n", + " )\n", + " bracket_avg = float(\n", + " np.average(change_arr[mask], weights=weight_arr[mask])\n", + " )\n", + " else:\n", + " bracket_cost = 0.0\n", + " bracket_avg = 0.0\n", + " by_income_bracket.append({\n", + " \"bracket\": label,\n", + " \"beneficiaries\": bracket_affected,\n", + " \"total_cost\": bracket_cost,\n", + " \"avg_benefit\": bracket_avg,\n", + " })\n", + "\n", + " return {\n", + " \"budget\": {\n", + " \"budgetary_impact\": tax_revenue_impact,\n", + " \"tax_revenue_impact\": tax_revenue_impact,\n", + " \"benefit_spending_impact\": 0.0,\n", + " \"households\": total_households,\n", + " },\n", + " \"decile\": {\n", + " \"average\": decile_average,\n", + " \"relative\": decile_relative,\n", + " },\n", + " \"intra_decile\": {\n", + " \"all\": intra_decile_all,\n", + " \"deciles\": intra_decile_deciles,\n", + " },\n", + " \"total_cost\": -tax_revenue_impact,\n", + " \"beneficiaries\": beneficiaries,\n", + " \"avg_benefit\": avg_benefit,\n", + " \"winners\": winners,\n", + " \"losers\": losers,\n", + " \"winners_rate\": winners_rate,\n", + " \"losers_rate\": losers_rate,\n", + " \"poverty_baseline_rate\": poverty_baseline_rate,\n", + " \"poverty_reform_rate\": poverty_reform_rate,\n", + " \"poverty_rate_change\": poverty_rate_change,\n", + " \"poverty_percent_change\": poverty_percent_change,\n", + " \"child_poverty_baseline_rate\": child_poverty_baseline_rate,\n", + " \"child_poverty_reform_rate\": child_poverty_reform_rate,\n", + " \"child_poverty_rate_change\": child_poverty_rate_change,\n", + " \"child_poverty_percent_change\": child_poverty_percent_change,\n", + " \"deep_poverty_baseline_rate\": deep_poverty_baseline_rate,\n", + " \"deep_poverty_reform_rate\": deep_poverty_reform_rate,\n", + " \"deep_poverty_rate_change\": deep_poverty_rate_change,\n", + " \"deep_poverty_percent_change\": deep_poverty_percent_change,\n", + " \"deep_child_poverty_baseline_rate\": deep_child_poverty_baseline_rate,\n", + " \"deep_child_poverty_reform_rate\": deep_child_poverty_reform_rate,\n", + " \"deep_child_poverty_rate_change\": deep_child_poverty_rate_change,\n", + " \"deep_child_poverty_percent_change\": deep_child_poverty_percent_change,\n", + " \"by_income_bracket\": by_income_bracket,\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": "# Calculate comprehensive 2026 impacts\nprint(\"Calculating comprehensive 2026 impacts...\")\nimpact_2026 = calculate_aggregate_impact(searchlight_reform, year=2026)\nprint(\"Done!\")\n\n# Export 2026 impact to CSV immediately\ndef export_2026_impact_to_csv(impact, filename):\n \"\"\"Export the 2026 impact results to a CSV file.\"\"\"\n rows = [\n [\"Metric\", \"Value\"],\n [\"Budgetary Impact ($)\", impact['budget']['budgetary_impact']],\n [\"Total Cost ($)\", impact['total_cost']],\n [\"Total Households\", impact['budget']['households']],\n [\"Winners\", impact['winners']],\n [\"Winners Rate (%)\", impact['winners_rate']],\n [\"Losers\", impact['losers']],\n [\"Losers Rate (%)\", impact['losers_rate']],\n [\"Beneficiaries\", impact['beneficiaries']],\n [\"Average Benefit ($)\", impact['avg_benefit']],\n [\"Poverty Baseline Rate (%)\", impact['poverty_baseline_rate']],\n [\"Poverty Reform Rate (%)\", impact['poverty_reform_rate']],\n [\"Poverty Rate Change (pp)\", impact['poverty_rate_change']],\n [\"Poverty Percent Change (%)\", impact['poverty_percent_change']],\n [\"Child Poverty Baseline Rate (%)\", impact['child_poverty_baseline_rate']],\n [\"Child Poverty Reform Rate (%)\", impact['child_poverty_reform_rate']],\n [\"Child Poverty Rate Change (pp)\", impact['child_poverty_rate_change']],\n [\"Child Poverty Percent Change (%)\", impact['child_poverty_percent_change']],\n [\"Deep Poverty Baseline Rate (%)\", impact['deep_poverty_baseline_rate']],\n [\"Deep Poverty Reform Rate (%)\", impact['deep_poverty_reform_rate']],\n [\"Deep Poverty Rate Change (pp)\", impact['deep_poverty_rate_change']],\n [\"Deep Poverty Percent Change (%)\", impact['deep_poverty_percent_change']],\n [\"Deep Child Poverty Baseline Rate (%)\", impact['deep_child_poverty_baseline_rate']],\n [\"Deep Child Poverty Reform Rate (%)\", impact['deep_child_poverty_reform_rate']],\n [\"Deep Child Poverty Rate Change (pp)\", impact['deep_child_poverty_rate_change']],\n [\"Deep Child Poverty Percent Change (%)\", impact['deep_child_poverty_percent_change']],\n ]\n \n # Add decile data\n for d in range(1, 11):\n rows.append([f\"Decile {d} Average Change ($)\", impact['decile']['average'][str(d)]])\n rows.append([f\"Decile {d} Relative Change\", impact['decile']['relative'][str(d)]])\n \n # Add income bracket data\n for bracket in impact['by_income_bracket']:\n rows.append([f\"Bracket {bracket['bracket']} Beneficiaries\", bracket['beneficiaries']])\n rows.append([f\"Bracket {bracket['bracket']} Total Cost ($)\", bracket['total_cost']])\n rows.append([f\"Bracket {bracket['bracket']} Avg Benefit ($)\", bracket['avg_benefit']])\n \n with open(filename, 'w', newline='') as f:\n writer = csv.writer(f)\n writer.writerows(rows)\n \n print(f\"2026 impact saved to {filename}\")\n\nexport_2026_impact_to_csv(impact_2026, \"reform_1_impact_2026.csv\")" + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "============================================================\n", + "BUDGET SUMMARY (2026)\n", + "============================================================\n", + "Budgetary Impact: $-154.16 billion\n", + "Total Cost: $154.16 billion\n", + "Total Households: 147,829,631\n" + ] + } + ], + "source": [ + "# Display budget summary\n", + "print(\"=\" * 60)\n", + "print(\"BUDGET SUMMARY (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"Budgetary Impact: ${impact_2026['budget']['budgetary_impact'] / 1e9:.2f} billion\")\n", + "print(f\"Total Cost: ${impact_2026['total_cost'] / 1e9:.2f} billion\")\n", + "print(f\"Total Households: {impact_2026['budget']['households']:,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "WINNERS / LOSERS (2026)\n", + "============================================================\n", + "Winners: 47,269,974 (32.0%)\n", + "Losers: 4,503,176 (3.0%)\n", + "Beneficiaries: 47,272,404\n", + "Average Benefit (affected): $2,977.68\n" + ] + } + ], + "source": [ + "# Display winners/losers\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"WINNERS / LOSERS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"Winners: {impact_2026['winners']:,.0f} ({impact_2026['winners_rate']:.1f}%)\")\n", + "print(f\"Losers: {impact_2026['losers']:,.0f} ({impact_2026['losers_rate']:.1f}%)\")\n", + "print(f\"Beneficiaries: {impact_2026['beneficiaries']:,.0f}\")\n", + "print(f\"Average Benefit (affected): ${impact_2026['avg_benefit']:,.2f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "POVERTY IMPACTS (2026)\n", + "============================================================\n", + "\n", + "Overall Poverty:\n", + " Baseline: 23.33%\n", + " Reform: 21.48%\n", + " Change: -1.85pp (-7.9%)\n", + "\n", + "Child Poverty:\n", + " Baseline: 22.00%\n", + " Reform: 16.98%\n", + " Change: -5.02pp (-22.8%)\n", + "\n", + "Deep Poverty:\n", + " Baseline: 8.70%\n", + " Reform: 7.36%\n", + " Change: -1.35pp (-15.5%)\n", + "\n", + "Deep Child Poverty:\n", + " Baseline: 8.56%\n", + " Reform: 5.33%\n", + " Change: -3.23pp (-37.7%)\n" + ] + } + ], + "source": [ + "# Display poverty impacts\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"POVERTY IMPACTS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"\\nOverall Poverty:\")\n", + "print(f\" Baseline: {impact_2026['poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['poverty_rate_change']:+.2f}pp ({impact_2026['poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nChild Poverty:\")\n", + "print(f\" Baseline: {impact_2026['child_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['child_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['child_poverty_rate_change']:+.2f}pp ({impact_2026['child_poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nDeep Poverty:\")\n", + "print(f\" Baseline: {impact_2026['deep_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['deep_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['deep_poverty_rate_change']:+.2f}pp ({impact_2026['deep_poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nDeep Child Poverty:\")\n", + "print(f\" Baseline: {impact_2026['deep_child_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['deep_child_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['deep_child_poverty_rate_change']:+.2f}pp ({impact_2026['deep_child_poverty_percent_change']:+.1f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "DECILE ANALYSIS (2026)\n", + "============================================================\n", + "Decile Avg Change Relative Change\n", + "---------------------------------------------\n", + "1 $ 929 8.06%\n", + "2 $ 1,014 3.79%\n", + "3 $ 905 2.26%\n", + "4 $ 1,425 2.63%\n", + "5 $ 1,896 2.69%\n", + "6 $ 1,187 1.37%\n", + "7 $ 1,189 1.07%\n", + "8 $ 1,155 0.79%\n", + "9 $ 517 0.26%\n", + "10 $ 202 0.03%\n" + ] + } + ], + "source": [ + "# Display decile analysis\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"DECILE ANALYSIS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"{'Decile':<10} {'Avg Change':>15} {'Relative Change':>18}\")\n", + "print(\"-\" * 45)\n", + "for d in range(1, 11):\n", + " avg = impact_2026['decile']['average'][str(d)]\n", + " rel = impact_2026['decile']['relative'][str(d)] * 100\n", + " print(f\"{d:<10} ${avg:>14,.0f} {rel:>17.2f}%\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "INCOME BRACKET BREAKDOWN (2026)\n", + "============================================================\n", + "Bracket Beneficiaries Total Cost Avg Benefit\n", + "------------------------------------------------------------\n", + "Under $50k 21,366,040 $ 74.28B $ 3,477\n", + "$50k-$100k 12,473,454 $ 41.58B $ 3,333\n", + "$100k-$200k 11,142,482 $ 31.15B $ 2,796\n", + "$200k-$500k 5,445,492 $ 2.53B $ 465\n", + "$500k-$1M 335,220 $ 0.72B $ 2,143\n", + "$1M-$2M 31,084 $ 0.05B $ 1,747\n", + "Over $2M 8,306 $ 0.01B $ 1,203\n" + ] + } + ], + "source": [ + "# Display income bracket breakdown\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"INCOME BRACKET BREAKDOWN (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"{'Bracket':<15} {'Beneficiaries':>15} {'Total Cost':>15} {'Avg Benefit':>12}\")\n", + "print(\"-\" * 60)\n", + "for bracket in impact_2026['by_income_bracket']:\n", + " print(f\"{bracket['bracket']:<15} {bracket['beneficiaries']:>15,.0f} ${bracket['total_cost']/1e9:>13.2f}B ${bracket['avg_benefit']:>10,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "#105293" + }, + "text": [ + "$929", + "$1,014", + "$905", + "$1,425", + "$1,896", + "$1,187", + "$1,189", + "$1,155", + "$517", + "$202" + ], + "textposition": "auto", + "type": "bar", + "x": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "y": [ + 928.6588902691982, + 1013.860060164923, + 905.2904728398725, + 1424.6851236296905, + 1895.8465136209072, + 1186.772328990473, + 1188.95953156828, + 1155.0580162318406, + 516.8394540088157, + 202.37838338438473 + ] + } + ], + "layout": { + "font": { + "color": "black", + "family": "Roboto Serif" + }, + "height": 600, + "images": [ + { + "sizex": 0.15, + "sizey": 0.15, + "source": "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png", + "x": 1.1, + "xanchor": "right", + "xref": "paper", + "y": -0.15, + "yanchor": "bottom", + "yref": "paper" + } + ], + "modebar": { + "bgcolor": "rgba(0,0,0,0)", + "color": "rgba(0,0,0,0)" + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "white", + "showlakes": true, + "showland": true, + "subunitcolor": "#C8D4E3" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "white", + "polar": { + "angularaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + }, + "bgcolor": "white", + "radialaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "yaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "zaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "baxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "bgcolor": "white", + "caxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Average Income Change by Decile (2026)" + }, + "width": 800, + "xaxis": { + "tickmode": "linear", + "title": { + "text": "Income Decile" + } + }, + "yaxis": { + "title": { + "text": "Average Change ($)" + } + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create decile bar chart\n", + "deciles = list(range(1, 11))\n", + "avg_changes = [impact_2026['decile']['average'][str(d)] for d in deciles]\n", + "\n", + "fig = go.Figure(\n", + " go.Bar(\n", + " x=deciles,\n", + " y=avg_changes,\n", + " text=[f\"${v:,.0f}\" for v in avg_changes],\n", + " textposition=\"auto\",\n", + " marker_color=\"#105293\",\n", + " )\n", + ")\n", + "\n", + "fig.update_layout(\n", + " title=\"Average Income Change by Decile (2026)\",\n", + " xaxis_title=\"Income Decile\",\n", + " yaxis_title=\"Average Change ($)\",\n", + " xaxis=dict(tickmode=\"linear\"),\n", + ")\n", + "\n", + "format_fig(fig).show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 10-Year Federal Budgetary Impact (2026-2035)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_budgetary_impact(reform, year):\n", + " \"\"\"Calculate just the federal income tax budgetary impact for a single year.\"\"\"\n", + " baseline = Microsimulation(dataset=DATASET)\n", + " reformed = Microsimulation(reform=reform, dataset=DATASET)\n", + " \n", + " baseline_income_tax = baseline.calculate(\"income_tax\", period=year).sum()\n", + " reformed_income_tax = reformed.calculate(\"income_tax\", period=year).sum()\n", + " \n", + " # Budgetary impact: negative means costs money (reform reduces tax revenue)\n", + " impact = reformed_income_tax - baseline_income_tax\n", + " return float(impact)\n", + "\n", + "\n", + "def calculate_ten_year_projection(reform, csv_filename=\"reform_1_10year_budgetary_impact.csv\"):\n", + " results = []\n", + "\n", + " with open(csv_filename, \"w\", newline=\"\") as csvfile:\n", + " csvwriter = csv.writer(csvfile)\n", + " csvwriter.writerow([\"Year\", \"Budgetary Impact\"])\n", + "\n", + " for year in range(2026, 2036):\n", + " print(f\"Computing budgetary impact for year {year}...\")\n", + " impact = calculate_budgetary_impact(reform, year)\n", + " results.append({\"Year\": year, \"Budgetary Impact\": impact})\n", + "\n", + " csvwriter.writerow([year, impact])\n", + " print(f\"Year {year} completed. Impact: ${impact/1e9:.2f} billion\")\n", + "\n", + " print(f\"All calculations complete. Results saved to '{csv_filename}'\")\n", + " return pd.DataFrame(results)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting 10-year budgetary impact calculation...\n", + "Computing budgetary impact for year 2026...\n", + "Year 2026 completed. Impact: $-154.16 billion\n", + "Computing budgetary impact for year 2027...\n", + "Year 2027 completed. Impact: $-157.86 billion\n", + "Computing budgetary impact for year 2028...\n", + "Year 2028 completed. Impact: $-164.60 billion\n", + "Computing budgetary impact for year 2029...\n", + "Year 2029 completed. Impact: $-167.29 billion\n", + "Computing budgetary impact for year 2030...\n", + "Year 2030 completed. Impact: $-175.56 billion\n", + "Computing budgetary impact for year 2031...\n", + "Year 2031 completed. Impact: $-169.57 billion\n", + "Computing budgetary impact for year 2032...\n", + "Year 2032 completed. Impact: $-176.60 billion\n", + "Computing budgetary impact for year 2033...\n", + "Year 2033 completed. Impact: $-178.46 billion\n", + "Computing budgetary impact for year 2034...\n", + "Year 2034 completed. Impact: $-177.02 billion\n", + "Computing budgetary impact for year 2035...\n", + "Year 2035 completed. Impact: $-180.12 billion\n", + "All calculations complete. Results saved to 'reform_1_10year_budgetary_impact.csv'\n", + "\n", + "Calculation complete. Summary of results:\n", + " Year Budgetary Impact\n", + "0 2026 -1.541640e+11\n", + "1 2027 -1.578641e+11\n", + "2 2028 -1.645973e+11\n", + "3 2029 -1.672875e+11\n", + "4 2030 -1.755564e+11\n", + "5 2031 -1.695734e+11\n", + "6 2032 -1.765993e+11\n", + "7 2033 -1.784634e+11\n", + "8 2034 -1.770176e+11\n", + "9 2035 -1.801237e+11\n", + "\n", + "10-Year Total: $-1701.25 billion\n" + ] + } + ], + "source": [ + "# Calculate 10-year projection\n", + "print(\"Starting 10-year budgetary impact calculation...\")\n", + "df_projection = calculate_ten_year_projection(searchlight_reform)\n", + "print(\"\\nCalculation complete. Summary of results:\")\n", + "print(df_projection)\n", + "print(f\"\\n10-Year Total: ${df_projection['Budgetary Impact'].sum() / 1e9:.2f} billion\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "#105293" + }, + "text": [ + "$-154.2B", + "$-157.9B", + "$-164.6B", + "$-167.3B", + "$-175.6B", + "$-169.6B", + "$-176.6B", + "$-178.5B", + "$-177.0B", + "$-180.1B" + ], + "textposition": "auto", + "type": "bar", + "x": [ + 2026, + 2027, + 2028, + 2029, + 2030, + 2031, + 2032, + 2033, + 2034, + 2035 + ], + "y": [ + -154.2, + -157.9, + -164.6, + -167.3, + -175.6, + -169.6, + -176.6, + -178.5, + -177, + -180.1 + ] + } + ], + "layout": { + "font": { + "color": "black", + "family": "Roboto Serif" + }, + "height": 600, + "images": [ + { + "sizex": 0.15, + "sizey": 0.15, + "source": "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png", + "x": 1.1, + "xanchor": "right", + "xref": "paper", + "y": -0.15, + "yanchor": "bottom", + "yref": "paper" + } + ], + "modebar": { + "bgcolor": "rgba(0,0,0,0)", + "color": "rgba(0,0,0,0)" + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "white", + "showlakes": true, + "showland": true, + "subunitcolor": "#C8D4E3" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "white", + "polar": { + "angularaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + }, + "bgcolor": "white", + "radialaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "yaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "zaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "baxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "bgcolor": "white", + "caxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "10-Year Federal Budgetary Impact of Searchlight Institute Tax Reform" + }, + "width": 800, + "xaxis": { + "tickmode": "linear", + "title": { + "text": "Year" + } + }, + "yaxis": { + "title": { + "text": "Budgetary Impact (Billions $)" + }, + "zeroline": true, + "zerolinecolor": "Black", + "zerolinewidth": 2 + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create 10-year bar chart\n", + "fig = go.Figure(\n", + " go.Bar(\n", + " x=df_projection[\"Year\"],\n", + " y=(df_projection[\"Budgetary Impact\"] / 1e9).round(1),\n", + " text=(df_projection[\"Budgetary Impact\"] / 1e9)\n", + " .round(1)\n", + " .apply(lambda x: f\"${x:.1f}B\"),\n", + " textposition=\"auto\",\n", + " marker_color=\"#105293\",\n", + " )\n", + ")\n", + "\n", + "fig.update_layout(\n", + " title=\"10-Year Federal Budgetary Impact of Searchlight Institute Tax Reform\",\n", + " xaxis_title=\"Year\",\n", + " yaxis_title=\"Budgetary Impact (Billions $)\",\n", + " xaxis=dict(tickmode=\"linear\"),\n", + " yaxis=dict(zeroline=True, zerolinewidth=2, zerolinecolor=\"Black\"),\n", + ")\n", + "\n", + "format_fig(fig).show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file diff --git a/us/searchlight_institute/reform_1_impact_2026.csv b/us/searchlight_institute/reform_1_impact_2026.csv new file mode 100644 index 0000000..9d258b7 --- /dev/null +++ b/us/searchlight_institute/reform_1_impact_2026.csv @@ -0,0 +1,67 @@ +Metric,Value +Budgetary Impact ($),-154164001783.69482 +Total Cost ($),154164001783.69482 +Total Households,147829631.20700648 +Winners,47269974.12108015 +Winners Rate (%),31.97598054945277 +Losers,4503176.1464319825 +Losers Rate (%),3.046193181748634 +Beneficiaries,47272404.40269636 +Average Benefit ($),2977.682461745086 +Poverty Baseline Rate (%),23.33367114033999 +Poverty Reform Rate (%),21.48264999239379 +Poverty Rate Change (pp),-1.8510211479462022 +Poverty Percent Change (%),-7.932832929774595 +Child Poverty Baseline Rate (%),21.99616050720215 +Child Poverty Reform Rate (%),16.97791862487793 +Child Poverty Rate Change (pp),-5.018241882324219 +Child Poverty Percent Change (%),-22.81417195824293 +Deep Poverty Baseline Rate (%),8.704698989314954 +Deep Poverty Reform Rate (%),7.359397582463532 +Deep Poverty Rate Change (pp),-1.345301406851422 +Deep Poverty Percent Change (%),-15.454887164998857 +Deep Child Poverty Baseline Rate (%),8.560979843139648 +Deep Child Poverty Reform Rate (%),5.333736896514893 +Deep Child Poverty Rate Change (pp),-3.227242946624756 +Deep Child Poverty Percent Change (%),-37.69712119122568 +Decile 1 Average Change ($),928.6588902691982 +Decile 1 Relative Change,0.08058464997765222 +Decile 2 Average Change ($),1013.860060164923 +Decile 2 Relative Change,0.03788473652062977 +Decile 3 Average Change ($),905.2904728398725 +Decile 3 Relative Change,0.022557856462306153 +Decile 4 Average Change ($),1424.6851236296905 +Decile 4 Relative Change,0.026272045978258943 +Decile 5 Average Change ($),1895.8465136209072 +Decile 5 Relative Change,0.026900278418685853 +Decile 6 Average Change ($),1186.772328990473 +Decile 6 Relative Change,0.013732198136512103 +Decile 7 Average Change ($),1188.95953156828 +Decile 7 Relative Change,0.01074242836086731 +Decile 8 Average Change ($),1155.0580162318406 +Decile 8 Relative Change,0.007910681803679423 +Decile 9 Average Change ($),516.8394540088157 +Decile 9 Relative Change,0.0026322721443851798 +Decile 10 Average Change ($),202.37838338438473 +Decile 10 Relative Change,0.0003007086056034714 +Bracket Under $50k Beneficiaries,21366040.0 +Bracket Under $50k Total Cost ($),74282020327.1552 +Bracket Under $50k Avg Benefit ($),3476.6397280520423 +Bracket $50k-$100k Beneficiaries,12473454.0 +Bracket $50k-$100k Total Cost ($),41576957126.07248 +Bracket $50k-$100k Avg Benefit ($),3333.2353940170988 +Bracket $100k-$200k Beneficiaries,11142482.0 +Bracket $100k-$200k Total Cost ($),31149494526.677044 +Bracket $100k-$200k Avg Benefit ($),2795.5615572901925 +Bracket $200k-$500k Beneficiaries,5445492.5 +Bracket $200k-$500k Total Cost ($),2531703154.8642535 +Bracket $200k-$500k Avg Benefit ($),464.9172064614434 +Bracket $500k-$1M Beneficiaries,335220.34375 +Bracket $500k-$1M Total Cost ($),718364347.578026 +Bracket $500k-$1M Avg Benefit ($),2142.9616745581297 +Bracket $1M-$2M Beneficiaries,31083.828125 +Bracket $1M-$2M Total Cost ($),54299420.781647265 +Bracket $1M-$2M Avg Benefit ($),1746.87052193152 +Bracket Over $2M Beneficiaries,8306.05078125 +Bracket Over $2M Total Cost ($),9991288.998794517 +Bracket Over $2M Avg Benefit ($),1202.892847495311 diff --git a/us/searchlight_institute/reform_2_10year_budgetary_impact.csv b/us/searchlight_institute/reform_2_10year_budgetary_impact.csv new file mode 100644 index 0000000..76ba2a4 --- /dev/null +++ b/us/searchlight_institute/reform_2_10year_budgetary_impact.csv @@ -0,0 +1,11 @@ +Year,Budgetary Impact +2026,-113443058010.38525 +2027,-116917420275.06738 +2028,-115483459551.44727 +2029,-118023403343.2334 +2030,-117954640627.83398 +2031,-120339708164.2998 +2032,-119068772615.61719 +2033,-121038947456.34717 +2034,-127727125431.44092 +2035,-122594164546.56543 diff --git a/us/searchlight_institute/reform_2_analysis.ipynb b/us/searchlight_institute/reform_2_analysis.ipynb new file mode 100644 index 0000000..1a96365 --- /dev/null +++ b/us/searchlight_institute/reform_2_analysis.ipynb @@ -0,0 +1,2752 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Searchlight Institute Tax Reform Analysis - Reform 2\n", + "\n", + "This notebook analyzes the comprehensive impact of the Searchlight Institute tax reform proposal (Reform 2):\n", + "- Full aggregate impacts for 2026 (deciles, poverty, winners/losers, income brackets)\n", + "- 10-year federal budgetary impact (2026-2035)\n", + "\n", + "**CTC Amounts:** $3,000 (2026) to $3,600 (2035)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np\n", + "import plotly.graph_objects as go\n", + "from policyengine_core.charts import format_fig\n", + "import csv" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Searchlight Institute Tax Reform - Reform 2\n", + "# - AFA CTC reforms (lower CTC amounts)\n", + "# - EITC eligibility and amount changes\n", + "# - EITC joint bonus set equal to phase-out start values\n", + "\n", + "REFORM_DICT = {\n", + " \"gov.contrib.congress.afa.in_effect\": {\n", + " \"2026-01-01.2100-12-31\": True\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.amount.base\": {\n", + " \"2026-01-01.2026-12-31\": 3000,\n", + " \"2027-01-01.2028-12-31\": 3120,\n", + " \"2029-01-01.2030-12-31\": 3240,\n", + " \"2031-01-01.2032-12-31\": 3360,\n", + " \"2033-01-01.2033-12-31\": 3480,\n", + " \"2034-01-01.2035-12-31\": 3600\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.max\": {\n", + " \"2026-01-01.2100-12-31\": 200\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.min\": {\n", + " \"2026-01-01.2100-12-31\": 19\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.min_student\": {\n", + " \"2026-01-01.2100-12-31\": 24\n", + " },\n", + " \"gov.irs.credits.eitc.max[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 1502,\n", + " \"2027-01-01.2027-12-31\": 1577,\n", + " \"2028-01-01.2028-12-31\": 1610,\n", + " \"2029-01-01.2029-12-31\": 1645,\n", + " \"2030-01-01.2030-12-31\": 1678,\n", + " \"2031-01-01.2031-12-31\": 1712,\n", + " \"2032-01-01.2032-12-31\": 1746,\n", + " \"2033-01-01.2033-12-31\": 1779,\n", + " \"2034-01-01.2034-12-31\": 1815,\n", + " \"2035-01-01.2035-12-31\": 1851\n", + " },\n", + " \"gov.irs.credits.eitc.phase_in_rate[0].amount\": {\n", + " \"2026-01-01.2100-12-31\": 0.153\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.rate[0].amount\": {\n", + " \"2026-01-01.2100-12-31\": 0.153\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.start[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 11610,\n", + " \"2027-01-01.2027-12-31\": 12190,\n", + " \"2028-01-01.2028-12-31\": 12440,\n", + " \"2029-01-01.2029-12-31\": 12710,\n", + " \"2030-01-01.2030-12-31\": 12970,\n", + " \"2031-01-01.2031-12-31\": 13230,\n", + " \"2032-01-01.2032-12-31\": 13490,\n", + " \"2033-01-01.2033-12-31\": 13750,\n", + " \"2034-01-01.2034-12-31\": 14030,\n", + " \"2035-01-01.2035-12-31\": 14300\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.joint_bonus[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 11610,\n", + " \"2027-01-01.2027-12-31\": 12190,\n", + " \"2028-01-01.2028-12-31\": 12440,\n", + " \"2029-01-01.2029-12-31\": 12710,\n", + " \"2030-01-01.2030-12-31\": 12970,\n", + " \"2031-01-01.2031-12-31\": 13230,\n", + " \"2032-01-01.2032-12-31\": 13490,\n", + " \"2033-01-01.2033-12-31\": 13750,\n", + " \"2034-01-01.2034-12-31\": 14030,\n", + " \"2035-01-01.2035-12-31\": 14300\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.JOINT\": {\n", + " \"2026-01-01.2026-12-31\": 150000,\n", + " \"2027-01-01.2028-12-31\": 155000,\n", + " \"2029-01-01.2029-12-31\": 160000,\n", + " \"2030-01-01.2031-12-31\": 165000,\n", + " \"2032-01-01.2033-12-31\": 170000,\n", + " \"2034-01-01.2034-12-31\": 175000,\n", + " \"2035-01-01.2035-12-31\": 180000\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.SINGLE\": {\n", + " \"2026-01-01.2027-12-31\": 112500,\n", + " \"2028-01-01.2029-12-31\": 117500,\n", + " \"2030-01-01.2031-12-31\": 122500,\n", + " \"2032-01-01.2033-12-31\": 127500,\n", + " \"2034-01-01.2035-12-31\": 132500\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.SURVIVING_SPOUSE\": {\n", + " \"2026-01-01.2026-12-31\": 150000,\n", + " \"2027-01-01.2028-12-31\": 155000,\n", + " \"2029-01-01.2029-12-31\": 160000,\n", + " \"2030-01-01.2031-12-31\": 165000,\n", + " \"2032-01-01.2033-12-31\": 170000,\n", + " \"2034-01-01.2034-12-31\": 175000,\n", + " \"2035-01-01.2035-12-31\": 180000\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.HEAD_OF_HOUSEHOLD\": {\n", + " \"2026-01-01.2027-12-31\": 112500,\n", + " \"2028-01-01.2029-12-31\": 117500,\n", + " \"2030-01-01.2031-12-31\": 122500,\n", + " \"2032-01-01.2033-12-31\": 127500,\n", + " \"2034-01-01.2035-12-31\": 132500\n", + " }\n", + "}\n", + "\n", + "searchlight_reform = Reform.from_dict(REFORM_DICT, country_id=\"us\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comprehensive 2026 Impact Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Intra-decile bounds and labels\n", + "_INTRA_BOUNDS = [-np.inf, -0.05, -1e-3, 1e-3, 0.05, np.inf]\n", + "_INTRA_LABELS = [\n", + " \"Lose more than 5%\",\n", + " \"Lose less than 5%\",\n", + " \"No change\",\n", + " \"Gain less than 5%\",\n", + " \"Gain more than 5%\",\n", + "]\n", + "\n", + "DATASET = \"hf://policyengine/policyengine-us-data/enhanced_cps_2024.h5\"\n", + "\n", + "\n", + "def _poverty_metrics(baseline_rate, reform_rate):\n", + " \"\"\"Return rate change and percent change for a poverty metric.\"\"\"\n", + " rate_change = reform_rate - baseline_rate\n", + " percent_change = (\n", + " rate_change / baseline_rate * 100\n", + " if baseline_rate > 0\n", + " else 0.0\n", + " )\n", + " return rate_change, percent_change\n", + "\n", + "\n", + "def calculate_aggregate_impact(reform, year: int = 2026) -> dict:\n", + " sim_baseline = Microsimulation(dataset=DATASET)\n", + " sim_reform = Microsimulation(reform=reform, dataset=DATASET)\n", + "\n", + " # ===== FISCAL IMPACT =====\n", + " tax_baseline = sim_baseline.calculate(\n", + " \"income_tax\", period=year, map_to=\"household\"\n", + " )\n", + " tax_reform = sim_reform.calculate(\n", + " \"income_tax\", period=year, map_to=\"household\"\n", + " )\n", + " income_change = tax_baseline - tax_reform\n", + " tax_revenue_impact = float(-income_change.sum())\n", + "\n", + " # Total households\n", + " total_households = float((income_change * 0 + 1).sum())\n", + "\n", + " # ===== WINNERS / LOSERS =====\n", + " winners = float((income_change > 1).sum())\n", + " losers = float((income_change < -1).sum())\n", + " beneficiaries = float((income_change > 0).sum())\n", + "\n", + " affected = abs(income_change) > 1\n", + " affected_count = float(affected.sum())\n", + "\n", + " household_weight_early = sim_reform.calculate(\n", + " \"household_weight\", period=year\n", + " )\n", + " affected_mask = np.array(affected).astype(bool)\n", + " change_arr_early = np.array(income_change)\n", + " weight_arr_early = np.array(household_weight_early)\n", + " avg_benefit = (\n", + " float(np.average(\n", + " change_arr_early[affected_mask],\n", + " weights=weight_arr_early[affected_mask],\n", + " ))\n", + " if affected_count > 0\n", + " else 0.0\n", + " )\n", + "\n", + " winners_rate = winners / total_households * 100\n", + " losers_rate = losers / total_households * 100\n", + "\n", + " # ===== INCOME DECILE ANALYSIS =====\n", + " decile = sim_baseline.calculate(\n", + " \"household_income_decile\", period=year, map_to=\"household\"\n", + " )\n", + " baseline_net_income = sim_baseline.calculate(\n", + " \"household_net_income\", period=year, map_to=\"household\"\n", + " )\n", + "\n", + " decile_average = {}\n", + " decile_relative = {}\n", + " for d in range(1, 11):\n", + " dmask = decile == d\n", + " d_count = float(dmask.sum())\n", + " if d_count > 0:\n", + " d_change_sum = float(income_change[dmask].sum())\n", + " decile_average[str(d)] = d_change_sum / d_count\n", + " d_baseline_sum = float(baseline_net_income[dmask].sum())\n", + " decile_relative[str(d)] = (\n", + " d_change_sum / d_baseline_sum\n", + " if d_baseline_sum != 0\n", + " else 0.0\n", + " )\n", + " else:\n", + " decile_average[str(d)] = 0.0\n", + " decile_relative[str(d)] = 0.0\n", + "\n", + " # Intra-decile\n", + " household_weight = sim_reform.calculate(\n", + " \"household_weight\", period=year\n", + " )\n", + " people_per_hh = sim_baseline.calculate(\n", + " \"household_count_people\", period=year, map_to=\"household\"\n", + " )\n", + " capped_baseline = np.maximum(np.array(baseline_net_income), 1)\n", + " rel_change_arr = np.array(income_change) / capped_baseline\n", + "\n", + " decile_arr = np.array(decile)\n", + " weight_arr = np.array(household_weight)\n", + " people_weighted = np.array(people_per_hh) * weight_arr\n", + "\n", + " intra_decile_deciles = {label: [] for label in _INTRA_LABELS}\n", + " for d in range(1, 11):\n", + " dmask = decile_arr == d\n", + " d_people = people_weighted[dmask]\n", + " d_total_people = d_people.sum()\n", + " d_rel = rel_change_arr[dmask]\n", + "\n", + " for lower, upper, label in zip(\n", + " _INTRA_BOUNDS[:-1], _INTRA_BOUNDS[1:], _INTRA_LABELS\n", + " ):\n", + " in_group = (d_rel > lower) & (d_rel <= upper)\n", + " proportion = (\n", + " float(d_people[in_group].sum() / d_total_people)\n", + " if d_total_people > 0\n", + " else 0.0\n", + " )\n", + " intra_decile_deciles[label].append(proportion)\n", + "\n", + " intra_decile_all = {\n", + " label: sum(intra_decile_deciles[label]) / 10\n", + " for label in _INTRA_LABELS\n", + " }\n", + "\n", + " # ===== POVERTY IMPACT =====\n", + " pov_bl = sim_baseline.calculate(\n", + " \"in_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " pov_rf = sim_reform.calculate(\n", + " \"in_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " poverty_baseline_rate = float(pov_bl.mean() * 100)\n", + " poverty_reform_rate = float(pov_rf.mean() * 100)\n", + " poverty_rate_change, poverty_percent_change = _poverty_metrics(\n", + " poverty_baseline_rate, poverty_reform_rate\n", + " )\n", + "\n", + " # Child/deep poverty\n", + " age_arr = np.array(sim_baseline.calculate(\"age\", period=year))\n", + " is_child = age_arr < 18\n", + " pw_arr = np.array(sim_baseline.calculate(\"person_weight\", period=year))\n", + " child_w = pw_arr[is_child]\n", + " total_child_w = child_w.sum()\n", + "\n", + " pov_bl_arr = np.array(pov_bl).astype(bool)\n", + " pov_rf_arr = np.array(pov_rf).astype(bool)\n", + "\n", + " def _child_rate(arr):\n", + " return float(\n", + " (arr[is_child] * child_w).sum() / total_child_w * 100\n", + " ) if total_child_w > 0 else 0.0\n", + "\n", + " child_poverty_baseline_rate = _child_rate(pov_bl_arr)\n", + " child_poverty_reform_rate = _child_rate(pov_rf_arr)\n", + " child_poverty_rate_change, child_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " child_poverty_baseline_rate, child_poverty_reform_rate\n", + " )\n", + " )\n", + "\n", + " deep_bl = sim_baseline.calculate(\n", + " \"in_deep_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " deep_rf = sim_reform.calculate(\n", + " \"in_deep_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " deep_poverty_baseline_rate = float(deep_bl.mean() * 100)\n", + " deep_poverty_reform_rate = float(deep_rf.mean() * 100)\n", + " deep_poverty_rate_change, deep_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " deep_poverty_baseline_rate, deep_poverty_reform_rate\n", + " )\n", + " )\n", + "\n", + " deep_bl_arr = np.array(deep_bl).astype(bool)\n", + " deep_rf_arr = np.array(deep_rf).astype(bool)\n", + " deep_child_poverty_baseline_rate = _child_rate(deep_bl_arr)\n", + " deep_child_poverty_reform_rate = _child_rate(deep_rf_arr)\n", + " deep_child_poverty_rate_change, deep_child_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " deep_child_poverty_baseline_rate,\n", + " deep_child_poverty_reform_rate,\n", + " )\n", + " )\n", + "\n", + " # ===== INCOME BRACKET BREAKDOWN =====\n", + " agi = sim_reform.calculate(\n", + " \"adjusted_gross_income\", period=year, map_to=\"household\"\n", + " )\n", + " agi_arr = np.array(agi)\n", + " change_arr = np.array(income_change)\n", + " affected_mask = np.abs(change_arr) > 1\n", + "\n", + " income_brackets = [\n", + " (0, 50_000, \"Under $50k\"),\n", + " (50_000, 100_000, \"$50k-$100k\"),\n", + " (100_000, 200_000, \"$100k-$200k\"),\n", + " (200_000, 500_000, \"$200k-$500k\"),\n", + " (500_000, 1_000_000, \"$500k-$1M\"),\n", + " (1_000_000, 2_000_000, \"$1M-$2M\"),\n", + " (2_000_000, float(\"inf\"), \"Over $2M\"),\n", + " ]\n", + "\n", + " by_income_bracket = []\n", + " for min_inc, max_inc, label in income_brackets:\n", + " mask = (\n", + " (agi_arr >= min_inc)\n", + " & (agi_arr < max_inc)\n", + " & affected_mask\n", + " )\n", + " bracket_affected = float(weight_arr[mask].sum())\n", + " if bracket_affected > 0:\n", + " bracket_cost = float(\n", + " (change_arr[mask] * weight_arr[mask]).sum()\n", + " )\n", + " bracket_avg = float(\n", + " np.average(change_arr[mask], weights=weight_arr[mask])\n", + " )\n", + " else:\n", + " bracket_cost = 0.0\n", + " bracket_avg = 0.0\n", + " by_income_bracket.append({\n", + " \"bracket\": label,\n", + " \"beneficiaries\": bracket_affected,\n", + " \"total_cost\": bracket_cost,\n", + " \"avg_benefit\": bracket_avg,\n", + " })\n", + "\n", + " return {\n", + " \"budget\": {\n", + " \"budgetary_impact\": tax_revenue_impact,\n", + " \"tax_revenue_impact\": tax_revenue_impact,\n", + " \"benefit_spending_impact\": 0.0,\n", + " \"households\": total_households,\n", + " },\n", + " \"decile\": {\n", + " \"average\": decile_average,\n", + " \"relative\": decile_relative,\n", + " },\n", + " \"intra_decile\": {\n", + " \"all\": intra_decile_all,\n", + " \"deciles\": intra_decile_deciles,\n", + " },\n", + " \"total_cost\": -tax_revenue_impact,\n", + " \"beneficiaries\": beneficiaries,\n", + " \"avg_benefit\": avg_benefit,\n", + " \"winners\": winners,\n", + " \"losers\": losers,\n", + " \"winners_rate\": winners_rate,\n", + " \"losers_rate\": losers_rate,\n", + " \"poverty_baseline_rate\": poverty_baseline_rate,\n", + " \"poverty_reform_rate\": poverty_reform_rate,\n", + " \"poverty_rate_change\": poverty_rate_change,\n", + " \"poverty_percent_change\": poverty_percent_change,\n", + " \"child_poverty_baseline_rate\": child_poverty_baseline_rate,\n", + " \"child_poverty_reform_rate\": child_poverty_reform_rate,\n", + " \"child_poverty_rate_change\": child_poverty_rate_change,\n", + " \"child_poverty_percent_change\": child_poverty_percent_change,\n", + " \"deep_poverty_baseline_rate\": deep_poverty_baseline_rate,\n", + " \"deep_poverty_reform_rate\": deep_poverty_reform_rate,\n", + " \"deep_poverty_rate_change\": deep_poverty_rate_change,\n", + " \"deep_poverty_percent_change\": deep_poverty_percent_change,\n", + " \"deep_child_poverty_baseline_rate\": deep_child_poverty_baseline_rate,\n", + " \"deep_child_poverty_reform_rate\": deep_child_poverty_reform_rate,\n", + " \"deep_child_poverty_rate_change\": deep_child_poverty_rate_change,\n", + " \"deep_child_poverty_percent_change\": deep_child_poverty_percent_change,\n", + " \"by_income_bracket\": by_income_bracket,\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating comprehensive 2026 impacts...\n", + "Done!\n", + "2026 impact saved to reform_2_impact_2026.csv\n" + ] + } + ], + "source": [ + "# Calculate comprehensive 2026 impacts\n", + "print(\"Calculating comprehensive 2026 impacts...\")\n", + "impact_2026 = calculate_aggregate_impact(searchlight_reform, year=2026)\n", + "print(\"Done!\")\n", + "\n", + "# Export 2026 impact to CSV immediately\n", + "def export_2026_impact_to_csv(impact, filename):\n", + " \"\"\"Export the 2026 impact results to a CSV file.\"\"\"\n", + " rows = [\n", + " [\"Metric\", \"Value\"],\n", + " [\"Budgetary Impact ($)\", impact['budget']['budgetary_impact']],\n", + " [\"Total Cost ($)\", impact['total_cost']],\n", + " [\"Total Households\", impact['budget']['households']],\n", + " [\"Winners\", impact['winners']],\n", + " [\"Winners Rate (%)\", impact['winners_rate']],\n", + " [\"Losers\", impact['losers']],\n", + " [\"Losers Rate (%)\", impact['losers_rate']],\n", + " [\"Beneficiaries\", impact['beneficiaries']],\n", + " [\"Average Benefit ($)\", impact['avg_benefit']],\n", + " [\"Poverty Baseline Rate (%)\", impact['poverty_baseline_rate']],\n", + " [\"Poverty Reform Rate (%)\", impact['poverty_reform_rate']],\n", + " [\"Poverty Rate Change (pp)\", impact['poverty_rate_change']],\n", + " [\"Poverty Percent Change (%)\", impact['poverty_percent_change']],\n", + " [\"Child Poverty Baseline Rate (%)\", impact['child_poverty_baseline_rate']],\n", + " [\"Child Poverty Reform Rate (%)\", impact['child_poverty_reform_rate']],\n", + " [\"Child Poverty Rate Change (pp)\", impact['child_poverty_rate_change']],\n", + " [\"Child Poverty Percent Change (%)\", impact['child_poverty_percent_change']],\n", + " [\"Deep Poverty Baseline Rate (%)\", impact['deep_poverty_baseline_rate']],\n", + " [\"Deep Poverty Reform Rate (%)\", impact['deep_poverty_reform_rate']],\n", + " [\"Deep Poverty Rate Change (pp)\", impact['deep_poverty_rate_change']],\n", + " [\"Deep Poverty Percent Change (%)\", impact['deep_poverty_percent_change']],\n", + " [\"Deep Child Poverty Baseline Rate (%)\", impact['deep_child_poverty_baseline_rate']],\n", + " [\"Deep Child Poverty Reform Rate (%)\", impact['deep_child_poverty_reform_rate']],\n", + " [\"Deep Child Poverty Rate Change (pp)\", impact['deep_child_poverty_rate_change']],\n", + " [\"Deep Child Poverty Percent Change (%)\", impact['deep_child_poverty_percent_change']],\n", + " ]\n", + " \n", + " # Add decile data\n", + " for d in range(1, 11):\n", + " rows.append([f\"Decile {d} Average Change ($)\", impact['decile']['average'][str(d)]])\n", + " rows.append([f\"Decile {d} Relative Change\", impact['decile']['relative'][str(d)]])\n", + " \n", + " # Add income bracket data\n", + " for bracket in impact['by_income_bracket']:\n", + " rows.append([f\"Bracket {bracket['bracket']} Beneficiaries\", bracket['beneficiaries']])\n", + " rows.append([f\"Bracket {bracket['bracket']} Total Cost ($)\", bracket['total_cost']])\n", + " rows.append([f\"Bracket {bracket['bracket']} Avg Benefit ($)\", bracket['avg_benefit']])\n", + " \n", + " with open(filename, 'w', newline='') as f:\n", + " writer = csv.writer(f)\n", + " writer.writerows(rows)\n", + " \n", + " print(f\"2026 impact saved to {filename}\")\n", + "\n", + "export_2026_impact_to_csv(impact_2026, \"reform_2_impact_2026.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "============================================================\n", + "BUDGET SUMMARY (2026) - Reform 2\n", + "============================================================\n", + "Budgetary Impact: $-113.44 billion\n", + "Total Cost: $113.44 billion\n", + "Total Households: 147,829,631\n" + ] + } + ], + "source": [ + "# Display budget summary\n", + "print(\"=\" * 60)\n", + "print(\"BUDGET SUMMARY (2026) - Reform 2\")\n", + "print(\"=\" * 60)\n", + "print(f\"Budgetary Impact: ${impact_2026['budget']['budgetary_impact'] / 1e9:.2f} billion\")\n", + "print(f\"Total Cost: ${impact_2026['total_cost'] / 1e9:.2f} billion\")\n", + "print(f\"Total Households: {impact_2026['budget']['households']:,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "WINNERS / LOSERS (2026)\n", + "============================================================\n", + "Winners: 46,577,942 (31.5%)\n", + "Losers: 5,164,542 (3.5%)\n", + "Beneficiaries: 46,580,372\n", + "Average Benefit (affected): $2,192.45\n" + ] + } + ], + "source": [ + "# Display winners/losers\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"WINNERS / LOSERS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"Winners: {impact_2026['winners']:,.0f} ({impact_2026['winners_rate']:.1f}%)\")\n", + "print(f\"Losers: {impact_2026['losers']:,.0f} ({impact_2026['losers_rate']:.1f}%)\")\n", + "print(f\"Beneficiaries: {impact_2026['beneficiaries']:,.0f}\")\n", + "print(f\"Average Benefit (affected): ${impact_2026['avg_benefit']:,.2f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "POVERTY IMPACTS (2026)\n", + "============================================================\n", + "\n", + "Overall Poverty:\n", + " Baseline: 23.33%\n", + " Reform: 21.58%\n", + " Change: -1.76pp (-7.5%)\n", + "\n", + "Child Poverty:\n", + " Baseline: 22.00%\n", + " Reform: 17.24%\n", + " Change: -4.76pp (-21.6%)\n", + "\n", + "Deep Poverty:\n", + " Baseline: 8.70%\n", + " Reform: 7.46%\n", + " Change: -1.24pp (-14.3%)\n", + "\n", + "Deep Child Poverty:\n", + " Baseline: 8.56%\n", + " Reform: 5.57%\n", + " Change: -2.99pp (-35.0%)\n" + ] + } + ], + "source": [ + "# Display poverty impacts\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"POVERTY IMPACTS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"\\nOverall Poverty:\")\n", + "print(f\" Baseline: {impact_2026['poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['poverty_rate_change']:+.2f}pp ({impact_2026['poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nChild Poverty:\")\n", + "print(f\" Baseline: {impact_2026['child_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['child_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['child_poverty_rate_change']:+.2f}pp ({impact_2026['child_poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nDeep Poverty:\")\n", + "print(f\" Baseline: {impact_2026['deep_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['deep_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['deep_poverty_rate_change']:+.2f}pp ({impact_2026['deep_poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nDeep Child Poverty:\")\n", + "print(f\" Baseline: {impact_2026['deep_child_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['deep_child_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['deep_child_poverty_rate_change']:+.2f}pp ({impact_2026['deep_child_poverty_percent_change']:+.1f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "DECILE ANALYSIS (2026)\n", + "============================================================\n", + "Decile Avg Change Relative Change\n", + "---------------------------------------------\n", + "1 $ 781 6.78%\n", + "2 $ 820 3.06%\n", + "3 $ 716 1.78%\n", + "4 $ 1,091 2.01%\n", + "5 $ 1,369 1.94%\n", + "6 $ 839 0.97%\n", + "7 $ 785 0.71%\n", + "8 $ 724 0.50%\n", + "9 $ 287 0.15%\n", + "10 $ 128 0.02%\n" + ] + } + ], + "source": [ + "# Display decile analysis\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"DECILE ANALYSIS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"{'Decile':<10} {'Avg Change':>15} {'Relative Change':>18}\")\n", + "print(\"-\" * 45)\n", + "for d in range(1, 11):\n", + " avg = impact_2026['decile']['average'][str(d)]\n", + " rel = impact_2026['decile']['relative'][str(d)] * 100\n", + " print(f\"{d:<10} ${avg:>14,.0f} {rel:>17.2f}%\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "INCOME BRACKET BREAKDOWN (2026)\n", + "============================================================\n", + "Bracket Beneficiaries Total Cost Avg Benefit\n", + "------------------------------------------------------------\n", + "Under $50k 21,366,040 $ 59.49B $ 2,784\n", + "$50k-$100k 12,473,454 $ 29.25B $ 2,345\n", + "$100k-$200k 11,142,482 $ 20.05B $ 1,799\n", + "$200k-$500k 5,414,826 $ 0.93B $ 171\n", + "$500k-$1M 335,220 $ 0.57B $ 1,707\n", + "$1M-$2M 31,084 $ 0.03B $ 1,045\n", + "Over $2M 8,306 $ 0.01B $ 1,042\n" + ] + } + ], + "source": [ + "# Display income bracket breakdown\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"INCOME BRACKET BREAKDOWN (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"{'Bracket':<15} {'Beneficiaries':>15} {'Total Cost':>15} {'Avg Benefit':>12}\")\n", + "print(\"-\" * 60)\n", + "for bracket in impact_2026['by_income_bracket']:\n", + " print(f\"{bracket['bracket']:<15} {bracket['beneficiaries']:>15,.0f} ${bracket['total_cost']/1e9:>13.2f}B ${bracket['avg_benefit']:>10,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "#105293" + }, + "text": [ + "$781", + "$820", + "$716", + "$1,091", + "$1,369", + "$839", + "$785", + "$724", + "$287", + "$128" + ], + "textposition": "auto", + "type": "bar", + "x": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "y": [ + 780.7994376313029, + 819.7589977614161, + 716.0136011089401, + 1090.7765528530292, + 1368.5481380089811, + 839.4528537162716, + 784.6251589674583, + 724.3633889757866, + 287.24881202593866, + 127.73573753264132 + ] + } + ], + "layout": { + "font": { + "color": "black", + "family": "Roboto Serif" + }, + "height": 600, + "images": [ + { + "sizex": 0.15, + "sizey": 0.15, + "source": "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png", + "x": 1.1, + "xanchor": "right", + "xref": "paper", + "y": -0.15, + "yanchor": "bottom", + "yref": "paper" + } + ], + "modebar": { + "bgcolor": "rgba(0,0,0,0)", + "color": "rgba(0,0,0,0)" + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "white", + "showlakes": true, + "showland": true, + "subunitcolor": "#C8D4E3" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "white", + "polar": { + "angularaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + }, + "bgcolor": "white", + "radialaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "yaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "zaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "baxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "bgcolor": "white", + "caxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Average Income Change by Decile (2026) - Reform 2" + }, + "width": 800, + "xaxis": { + "tickmode": "linear", + "title": { + "text": "Income Decile" + } + }, + "yaxis": { + "title": { + "text": "Average Change ($)" + } + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create decile bar chart\n", + "deciles = list(range(1, 11))\n", + "avg_changes = [impact_2026['decile']['average'][str(d)] for d in deciles]\n", + "\n", + "fig = go.Figure(\n", + " go.Bar(\n", + " x=deciles,\n", + " y=avg_changes,\n", + " text=[f\"${v:,.0f}\" for v in avg_changes],\n", + " textposition=\"auto\",\n", + " marker_color=\"#105293\",\n", + " )\n", + ")\n", + "\n", + "fig.update_layout(\n", + " title=\"Average Income Change by Decile (2026) - Reform 2\",\n", + " xaxis_title=\"Income Decile\",\n", + " yaxis_title=\"Average Change ($)\",\n", + " xaxis=dict(tickmode=\"linear\"),\n", + ")\n", + "\n", + "format_fig(fig).show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 10-Year Federal Budgetary Impact (2026-2035)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_budgetary_impact(reform, year):\n", + " \"\"\"Calculate just the federal income tax budgetary impact for a single year.\"\"\"\n", + " baseline = Microsimulation(dataset=DATASET)\n", + " reformed = Microsimulation(reform=reform, dataset=DATASET)\n", + " \n", + " baseline_income_tax = baseline.calculate(\"income_tax\", period=year).sum()\n", + " reformed_income_tax = reformed.calculate(\"income_tax\", period=year).sum()\n", + " \n", + " # Budgetary impact: negative means costs money (reform reduces tax revenue)\n", + " impact = reformed_income_tax - baseline_income_tax\n", + " return float(impact)\n", + "\n", + "\n", + "def calculate_ten_year_projection(reform, csv_filename=\"reform_2_10year_budgetary_impact.csv\"):\n", + " results = []\n", + "\n", + " with open(csv_filename, \"w\", newline=\"\") as csvfile:\n", + " csvwriter = csv.writer(csvfile)\n", + " csvwriter.writerow([\"Year\", \"Budgetary Impact\"])\n", + "\n", + " for year in range(2026, 2036):\n", + " print(f\"Computing budgetary impact for year {year}...\")\n", + " impact = calculate_budgetary_impact(reform, year)\n", + " results.append({\"Year\": year, \"Budgetary Impact\": impact})\n", + "\n", + " csvwriter.writerow([year, impact])\n", + " print(f\"Year {year} completed. Impact: ${impact/1e9:.2f} billion\")\n", + "\n", + " print(f\"All calculations complete. Results saved to '{csv_filename}'\")\n", + " return pd.DataFrame(results)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting 10-year budgetary impact calculation...\n", + "Computing budgetary impact for year 2026...\n", + "Year 2026 completed. Impact: $-113.44 billion\n", + "Computing budgetary impact for year 2027...\n", + "Year 2027 completed. Impact: $-116.92 billion\n", + "Computing budgetary impact for year 2028...\n", + "Year 2028 completed. Impact: $-115.48 billion\n", + "Computing budgetary impact for year 2029...\n", + "Year 2029 completed. Impact: $-118.02 billion\n", + "Computing budgetary impact for year 2030...\n", + "Year 2030 completed. Impact: $-117.95 billion\n", + "Computing budgetary impact for year 2031...\n", + "Year 2031 completed. Impact: $-120.34 billion\n", + "Computing budgetary impact for year 2032...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6627d772c8d94732a64c67cf41681bf2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "enhanced_cps_2024.h5: 0%| | 0.00/111M [00:00here for more info. \n", + "\u001b[1;31mView Jupyter log for further details." + ] + } + ], + "source": [ + "# Create 10-year bar chart\n", + "fig = go.Figure(\n", + " go.Bar(\n", + " x=df_projection[\"Year\"],\n", + " y=(df_projection[\"Budgetary Impact\"] / 1e9).round(1),\n", + " text=(df_projection[\"Budgetary Impact\"] / 1e9)\n", + " .round(1)\n", + " .apply(lambda x: f\"${x:.1f}B\"),\n", + " textposition=\"auto\",\n", + " marker_color=\"#105293\",\n", + " )\n", + ")\n", + "\n", + "fig.update_layout(\n", + " title=\"10-Year Federal Budgetary Impact - Reform 2\",\n", + " xaxis_title=\"Year\",\n", + " yaxis_title=\"Budgetary Impact (Billions $)\",\n", + " xaxis=dict(tickmode=\"linear\"),\n", + " yaxis=dict(zeroline=True, zerolinewidth=2, zerolinecolor=\"Black\"),\n", + ")\n", + "\n", + "format_fig(fig).show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/us/searchlight_institute/reform_2_impact_2026.csv b/us/searchlight_institute/reform_2_impact_2026.csv new file mode 100644 index 0000000..daa9606 --- /dev/null +++ b/us/searchlight_institute/reform_2_impact_2026.csv @@ -0,0 +1,67 @@ +Metric,Value +Budgetary Impact ($),-113443058010.38493 +Total Cost ($),113443058010.38493 +Total Households,147829631.20700648 +Winners,46577941.902932726 +Winners Rate (%),31.507852331518997 +Losers,5164541.787064761 +Losers Rate (%),3.4935768593191106 +Beneficiaries,46580372.18454894 +Average Benefit ($),2192.4548200511676 +Poverty Baseline Rate (%),23.33367114033999 +Poverty Reform Rate (%),21.57605948274563 +Poverty Rate Change (pp),-1.75761165759436 +Poverty Percent Change (%),-7.532512338171019 +Child Poverty Baseline Rate (%),21.99616050720215 +Child Poverty Reform Rate (%),17.2364559173584 +Child Poverty Rate Change (pp),-4.75970458984375 +Child Poverty Percent Change (%),-21.638797317765032 +Deep Poverty Baseline Rate (%),8.704698989314954 +Deep Poverty Reform Rate (%),7.460981816878894 +Deep Poverty Rate Change (pp),-1.2437171724360603 +Deep Poverty Percent Change (%),-14.287882601830656 +Deep Child Poverty Baseline Rate (%),8.560979843139648 +Deep Child Poverty Reform Rate (%),5.567295074462891 +Deep Child Poverty Rate Change (pp),-2.993684768676758 +Deep Child Poverty Percent Change (%),-34.96895009133505 +Decile 1 Average Change ($),780.7994376313029 +Decile 1 Relative Change,0.0677541022258743 +Decile 2 Average Change ($),819.7589977614161 +Decile 2 Relative Change,0.030631795117321114 +Decile 3 Average Change ($),716.0136011089401 +Decile 3 Relative Change,0.017841491237841976 +Decile 4 Average Change ($),1090.7765528530292 +Decile 4 Relative Change,0.020114572176869443 +Decile 5 Average Change ($),1368.5481380089811 +Decile 5 Relative Change,0.019418410550284183 +Decile 6 Average Change ($),839.4528537162716 +Decile 6 Relative Change,0.009713348240347195 +Decile 7 Average Change ($),784.6251589674583 +Decile 7 Relative Change,0.007089206433480698 +Decile 8 Average Change ($),724.3633889757866 +Decile 8 Relative Change,0.004960970098381759 +Decile 9 Average Change ($),287.24881202593866 +Decile 9 Relative Change,0.001462963093353001 +Decile 10 Average Change ($),127.73573753264132 +Decile 10 Relative Change,0.00018979910243781178 +Bracket Under $50k Beneficiaries,21366040.0 +Bracket Under $50k Total Cost ($),59492600050.05449 +Bracket Under $50k Avg Benefit ($),2784.4468412165434 +Bracket $50k-$100k Beneficiaries,12473454.0 +Bracket $50k-$100k Total Cost ($),29245329235.191666 +Bracket $50k-$100k Avg Benefit ($),2344.6056001845836 +Bracket $100k-$200k Beneficiaries,11142482.0 +Bracket $100k-$200k Total Cost ($),20046131295.71265 +Bracket $100k-$200k Avg Benefit ($),1799.072340473846 +Bracket $200k-$500k Beneficiaries,5414826.0 +Bracket $200k-$500k Total Cost ($),927273512.4944108 +Bracket $200k-$500k Avg Benefit ($),171.2471514309523 +Bracket $500k-$1M Beneficiaries,335220.34375 +Bracket $500k-$1M Total Cost ($),572336491.7657435 +Bracket $500k-$1M Avg Benefit ($),1707.344150555614 +Bracket $1M-$2M Beneficiaries,31083.828125 +Bracket $1M-$2M Total Cost ($),32489950.99534661 +Bracket $1M-$2M Avg Benefit ($),1045.236520680412 +Bracket Over $2M Beneficiaries,8306.05078125 +Bracket Over $2M Total Cost ($),8653355.63597258 +Bracket Over $2M Avg Benefit ($),1041.8134839859545 diff --git a/us/searchlight_institute/reform_3_10year_budgetary_impact.csv b/us/searchlight_institute/reform_3_10year_budgetary_impact.csv new file mode 100644 index 0000000..02b07d5 --- /dev/null +++ b/us/searchlight_institute/reform_3_10year_budgetary_impact.csv @@ -0,0 +1,11 @@ +Year,Budgetary Impact +2026,-93467799629.98828 +2027,-96810364950.26514 +2028,-95475415012.12012 +2029,-97888295578.53516 +2030,-97841598248.82227 +2031,-100265266755.81348 +2032,-99055159267.96533 +2033,-101078701297.22852 +2034,-99763416803.51074 +2035,-102655575125.43213 diff --git a/us/searchlight_institute/reform_3_analysis.ipynb b/us/searchlight_institute/reform_3_analysis.ipynb new file mode 100644 index 0000000..ecc3367 --- /dev/null +++ b/us/searchlight_institute/reform_3_analysis.ipynb @@ -0,0 +1,2768 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Searchlight Institute Tax Reform Analysis - Reform 3\n", + "\n", + "This notebook analyzes the comprehensive impact of the Searchlight Institute tax reform proposal (Reform 3):\n", + "- Full aggregate impacts for 2026 (deciles, poverty, winners/losers, income brackets)\n", + "- 10-year federal budgetary impact (2026-2035)\n", + "\n", + "**CTC Amounts:** $2,700 (2026) to $3,240 (2035)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "import pandas as pd\n", + "import numpy as np\n", + "import plotly.graph_objects as go\n", + "from policyengine_core.charts import format_fig\n", + "import csv" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Searchlight Institute Tax Reform - Reform 3\n", + "# - AFA CTC reforms (lowest CTC amounts)\n", + "# - EITC eligibility and amount changes\n", + "# - EITC joint bonus set equal to phase-out start values\n", + "\n", + "REFORM_DICT = {\n", + " \"gov.contrib.congress.afa.in_effect\": {\n", + " \"2026-01-01.2100-12-31\": True\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.amount.base\": {\n", + " \"2026-01-01.2026-12-31\": 2700,\n", + " \"2027-01-01.2028-12-31\": 2820,\n", + " \"2029-01-01.2030-12-31\": 2940,\n", + " \"2031-01-01.2032-12-31\": 3060,\n", + " \"2033-01-01.2034-12-31\": 3180,\n", + " \"2035-01-01.2035-12-31\": 3300\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.max\": {\n", + " \"2026-01-01.2100-12-31\": 200\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.min\": {\n", + " \"2026-01-01.2100-12-31\": 19\n", + " },\n", + " \"gov.irs.credits.eitc.eligibility.age.min_student\": {\n", + " \"2026-01-01.2100-12-31\": 24\n", + " },\n", + " \"gov.irs.credits.eitc.max[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 1502,\n", + " \"2027-01-01.2027-12-31\": 1577,\n", + " \"2028-01-01.2028-12-31\": 1610,\n", + " \"2029-01-01.2029-12-31\": 1645,\n", + " \"2030-01-01.2030-12-31\": 1678,\n", + " \"2031-01-01.2031-12-31\": 1712,\n", + " \"2032-01-01.2032-12-31\": 1746,\n", + " \"2033-01-01.2033-12-31\": 1779,\n", + " \"2034-01-01.2034-12-31\": 1815,\n", + " \"2035-01-01.2035-12-31\": 1851\n", + " },\n", + " \"gov.irs.credits.eitc.phase_in_rate[0].amount\": {\n", + " \"2026-01-01.2100-12-31\": 0.153\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.rate[0].amount\": {\n", + " \"2026-01-01.2100-12-31\": 0.153\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.start[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 11610,\n", + " \"2027-01-01.2027-12-31\": 12190,\n", + " \"2028-01-01.2028-12-31\": 12440,\n", + " \"2029-01-01.2029-12-31\": 12710,\n", + " \"2030-01-01.2030-12-31\": 12970,\n", + " \"2031-01-01.2031-12-31\": 13230,\n", + " \"2032-01-01.2032-12-31\": 13490,\n", + " \"2033-01-01.2033-12-31\": 13750,\n", + " \"2034-01-01.2034-12-31\": 14030,\n", + " \"2035-01-01.2035-12-31\": 14300\n", + " },\n", + " \"gov.irs.credits.eitc.phase_out.joint_bonus[0].amount\": {\n", + " \"2026-01-01.2026-12-31\": 11610,\n", + " \"2027-01-01.2027-12-31\": 12190,\n", + " \"2028-01-01.2028-12-31\": 12440,\n", + " \"2029-01-01.2029-12-31\": 12710,\n", + " \"2030-01-01.2030-12-31\": 12970,\n", + " \"2031-01-01.2031-12-31\": 13230,\n", + " \"2032-01-01.2032-12-31\": 13490,\n", + " \"2033-01-01.2033-12-31\": 13750,\n", + " \"2034-01-01.2034-12-31\": 14030,\n", + " \"2035-01-01.2035-12-31\": 14300\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.JOINT\": {\n", + " \"2026-01-01.2026-12-31\": 150000,\n", + " \"2027-01-01.2028-12-31\": 155000,\n", + " \"2029-01-01.2029-12-31\": 160000,\n", + " \"2030-01-01.2031-12-31\": 165000,\n", + " \"2032-01-01.2033-12-31\": 170000,\n", + " \"2034-01-01.2034-12-31\": 175000,\n", + " \"2035-01-01.2035-12-31\": 180000\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.SINGLE\": {\n", + " \"2026-01-01.2027-12-31\": 112500,\n", + " \"2028-01-01.2029-12-31\": 117500,\n", + " \"2030-01-01.2031-12-31\": 122500,\n", + " \"2032-01-01.2033-12-31\": 127500,\n", + " \"2034-01-01.2035-12-31\": 132500\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.SURVIVING_SPOUSE\": {\n", + " \"2026-01-01.2026-12-31\": 150000,\n", + " \"2027-01-01.2028-12-31\": 155000,\n", + " \"2029-01-01.2029-12-31\": 160000,\n", + " \"2030-01-01.2031-12-31\": 165000,\n", + " \"2032-01-01.2033-12-31\": 170000,\n", + " \"2034-01-01.2034-12-31\": 175000,\n", + " \"2035-01-01.2035-12-31\": 180000\n", + " },\n", + " \"gov.contrib.congress.afa.ctc.phase_out.threshold.lower.HEAD_OF_HOUSEHOLD\": {\n", + " \"2026-01-01.2027-12-31\": 112500,\n", + " \"2028-01-01.2029-12-31\": 117500,\n", + " \"2030-01-01.2031-12-31\": 122500,\n", + " \"2032-01-01.2033-12-31\": 127500,\n", + " \"2034-01-01.2035-12-31\": 132500\n", + " }\n", + "}\n", + "\n", + "searchlight_reform = Reform.from_dict(REFORM_DICT, country_id=\"us\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comprehensive 2026 Impact Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Intra-decile bounds and labels\n", + "_INTRA_BOUNDS = [-np.inf, -0.05, -1e-3, 1e-3, 0.05, np.inf]\n", + "_INTRA_LABELS = [\n", + " \"Lose more than 5%\",\n", + " \"Lose less than 5%\",\n", + " \"No change\",\n", + " \"Gain less than 5%\",\n", + " \"Gain more than 5%\",\n", + "]\n", + "\n", + "DATASET = \"hf://policyengine/policyengine-us-data/enhanced_cps_2024.h5\"\n", + "\n", + "\n", + "def _poverty_metrics(baseline_rate, reform_rate):\n", + " \"\"\"Return rate change and percent change for a poverty metric.\"\"\"\n", + " rate_change = reform_rate - baseline_rate\n", + " percent_change = (\n", + " rate_change / baseline_rate * 100\n", + " if baseline_rate > 0\n", + " else 0.0\n", + " )\n", + " return rate_change, percent_change\n", + "\n", + "\n", + "def calculate_aggregate_impact(reform, year: int = 2026) -> dict:\n", + " sim_baseline = Microsimulation(dataset=DATASET)\n", + " sim_reform = Microsimulation(reform=reform, dataset=DATASET)\n", + "\n", + " # ===== FISCAL IMPACT =====\n", + " tax_baseline = sim_baseline.calculate(\n", + " \"income_tax\", period=year, map_to=\"household\"\n", + " )\n", + " tax_reform = sim_reform.calculate(\n", + " \"income_tax\", period=year, map_to=\"household\"\n", + " )\n", + " income_change = tax_baseline - tax_reform\n", + " tax_revenue_impact = float(-income_change.sum())\n", + "\n", + " # Total households\n", + " total_households = float((income_change * 0 + 1).sum())\n", + "\n", + " # ===== WINNERS / LOSERS =====\n", + " winners = float((income_change > 1).sum())\n", + " losers = float((income_change < -1).sum())\n", + " beneficiaries = float((income_change > 0).sum())\n", + "\n", + " affected = abs(income_change) > 1\n", + " affected_count = float(affected.sum())\n", + "\n", + " household_weight_early = sim_reform.calculate(\n", + " \"household_weight\", period=year\n", + " )\n", + " affected_mask = np.array(affected).astype(bool)\n", + " change_arr_early = np.array(income_change)\n", + " weight_arr_early = np.array(household_weight_early)\n", + " avg_benefit = (\n", + " float(np.average(\n", + " change_arr_early[affected_mask],\n", + " weights=weight_arr_early[affected_mask],\n", + " ))\n", + " if affected_count > 0\n", + " else 0.0\n", + " )\n", + "\n", + " winners_rate = winners / total_households * 100\n", + " losers_rate = losers / total_households * 100\n", + "\n", + " # ===== INCOME DECILE ANALYSIS =====\n", + " decile = sim_baseline.calculate(\n", + " \"household_income_decile\", period=year, map_to=\"household\"\n", + " )\n", + " baseline_net_income = sim_baseline.calculate(\n", + " \"household_net_income\", period=year, map_to=\"household\"\n", + " )\n", + "\n", + " decile_average = {}\n", + " decile_relative = {}\n", + " for d in range(1, 11):\n", + " dmask = decile == d\n", + " d_count = float(dmask.sum())\n", + " if d_count > 0:\n", + " d_change_sum = float(income_change[dmask].sum())\n", + " decile_average[str(d)] = d_change_sum / d_count\n", + " d_baseline_sum = float(baseline_net_income[dmask].sum())\n", + " decile_relative[str(d)] = (\n", + " d_change_sum / d_baseline_sum\n", + " if d_baseline_sum != 0\n", + " else 0.0\n", + " )\n", + " else:\n", + " decile_average[str(d)] = 0.0\n", + " decile_relative[str(d)] = 0.0\n", + "\n", + " # Intra-decile\n", + " household_weight = sim_reform.calculate(\n", + " \"household_weight\", period=year\n", + " )\n", + " people_per_hh = sim_baseline.calculate(\n", + " \"household_count_people\", period=year, map_to=\"household\"\n", + " )\n", + " capped_baseline = np.maximum(np.array(baseline_net_income), 1)\n", + " rel_change_arr = np.array(income_change) / capped_baseline\n", + "\n", + " decile_arr = np.array(decile)\n", + " weight_arr = np.array(household_weight)\n", + " people_weighted = np.array(people_per_hh) * weight_arr\n", + "\n", + " intra_decile_deciles = {label: [] for label in _INTRA_LABELS}\n", + " for d in range(1, 11):\n", + " dmask = decile_arr == d\n", + " d_people = people_weighted[dmask]\n", + " d_total_people = d_people.sum()\n", + " d_rel = rel_change_arr[dmask]\n", + "\n", + " for lower, upper, label in zip(\n", + " _INTRA_BOUNDS[:-1], _INTRA_BOUNDS[1:], _INTRA_LABELS\n", + " ):\n", + " in_group = (d_rel > lower) & (d_rel <= upper)\n", + " proportion = (\n", + " float(d_people[in_group].sum() / d_total_people)\n", + " if d_total_people > 0\n", + " else 0.0\n", + " )\n", + " intra_decile_deciles[label].append(proportion)\n", + "\n", + " intra_decile_all = {\n", + " label: sum(intra_decile_deciles[label]) / 10\n", + " for label in _INTRA_LABELS\n", + " }\n", + "\n", + " # ===== POVERTY IMPACT =====\n", + " pov_bl = sim_baseline.calculate(\n", + " \"in_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " pov_rf = sim_reform.calculate(\n", + " \"in_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " poverty_baseline_rate = float(pov_bl.mean() * 100)\n", + " poverty_reform_rate = float(pov_rf.mean() * 100)\n", + " poverty_rate_change, poverty_percent_change = _poverty_metrics(\n", + " poverty_baseline_rate, poverty_reform_rate\n", + " )\n", + "\n", + " # Child/deep poverty\n", + " age_arr = np.array(sim_baseline.calculate(\"age\", period=year))\n", + " is_child = age_arr < 18\n", + " pw_arr = np.array(sim_baseline.calculate(\"person_weight\", period=year))\n", + " child_w = pw_arr[is_child]\n", + " total_child_w = child_w.sum()\n", + "\n", + " pov_bl_arr = np.array(pov_bl).astype(bool)\n", + " pov_rf_arr = np.array(pov_rf).astype(bool)\n", + "\n", + " def _child_rate(arr):\n", + " return float(\n", + " (arr[is_child] * child_w).sum() / total_child_w * 100\n", + " ) if total_child_w > 0 else 0.0\n", + "\n", + " child_poverty_baseline_rate = _child_rate(pov_bl_arr)\n", + " child_poverty_reform_rate = _child_rate(pov_rf_arr)\n", + " child_poverty_rate_change, child_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " child_poverty_baseline_rate, child_poverty_reform_rate\n", + " )\n", + " )\n", + "\n", + " deep_bl = sim_baseline.calculate(\n", + " \"in_deep_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " deep_rf = sim_reform.calculate(\n", + " \"in_deep_poverty\", period=year, map_to=\"person\"\n", + " )\n", + " deep_poverty_baseline_rate = float(deep_bl.mean() * 100)\n", + " deep_poverty_reform_rate = float(deep_rf.mean() * 100)\n", + " deep_poverty_rate_change, deep_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " deep_poverty_baseline_rate, deep_poverty_reform_rate\n", + " )\n", + " )\n", + "\n", + " deep_bl_arr = np.array(deep_bl).astype(bool)\n", + " deep_rf_arr = np.array(deep_rf).astype(bool)\n", + " deep_child_poverty_baseline_rate = _child_rate(deep_bl_arr)\n", + " deep_child_poverty_reform_rate = _child_rate(deep_rf_arr)\n", + " deep_child_poverty_rate_change, deep_child_poverty_percent_change = (\n", + " _poverty_metrics(\n", + " deep_child_poverty_baseline_rate,\n", + " deep_child_poverty_reform_rate,\n", + " )\n", + " )\n", + "\n", + " # ===== INCOME BRACKET BREAKDOWN =====\n", + " agi = sim_reform.calculate(\n", + " \"adjusted_gross_income\", period=year, map_to=\"household\"\n", + " )\n", + " agi_arr = np.array(agi)\n", + " change_arr = np.array(income_change)\n", + " affected_mask = np.abs(change_arr) > 1\n", + "\n", + " income_brackets = [\n", + " (0, 50_000, \"Under $50k\"),\n", + " (50_000, 100_000, \"$50k-$100k\"),\n", + " (100_000, 200_000, \"$100k-$200k\"),\n", + " (200_000, 500_000, \"$200k-$500k\"),\n", + " (500_000, 1_000_000, \"$500k-$1M\"),\n", + " (1_000_000, 2_000_000, \"$1M-$2M\"),\n", + " (2_000_000, float(\"inf\"), \"Over $2M\"),\n", + " ]\n", + "\n", + " by_income_bracket = []\n", + " for min_inc, max_inc, label in income_brackets:\n", + " mask = (\n", + " (agi_arr >= min_inc)\n", + " & (agi_arr < max_inc)\n", + " & affected_mask\n", + " )\n", + " bracket_affected = float(weight_arr[mask].sum())\n", + " if bracket_affected > 0:\n", + " bracket_cost = float(\n", + " (change_arr[mask] * weight_arr[mask]).sum()\n", + " )\n", + " bracket_avg = float(\n", + " np.average(change_arr[mask], weights=weight_arr[mask])\n", + " )\n", + " else:\n", + " bracket_cost = 0.0\n", + " bracket_avg = 0.0\n", + " by_income_bracket.append({\n", + " \"bracket\": label,\n", + " \"beneficiaries\": bracket_affected,\n", + " \"total_cost\": bracket_cost,\n", + " \"avg_benefit\": bracket_avg,\n", + " })\n", + "\n", + " return {\n", + " \"budget\": {\n", + " \"budgetary_impact\": tax_revenue_impact,\n", + " \"tax_revenue_impact\": tax_revenue_impact,\n", + " \"benefit_spending_impact\": 0.0,\n", + " \"households\": total_households,\n", + " },\n", + " \"decile\": {\n", + " \"average\": decile_average,\n", + " \"relative\": decile_relative,\n", + " },\n", + " \"intra_decile\": {\n", + " \"all\": intra_decile_all,\n", + " \"deciles\": intra_decile_deciles,\n", + " },\n", + " \"total_cost\": -tax_revenue_impact,\n", + " \"beneficiaries\": beneficiaries,\n", + " \"avg_benefit\": avg_benefit,\n", + " \"winners\": winners,\n", + " \"losers\": losers,\n", + " \"winners_rate\": winners_rate,\n", + " \"losers_rate\": losers_rate,\n", + " \"poverty_baseline_rate\": poverty_baseline_rate,\n", + " \"poverty_reform_rate\": poverty_reform_rate,\n", + " \"poverty_rate_change\": poverty_rate_change,\n", + " \"poverty_percent_change\": poverty_percent_change,\n", + " \"child_poverty_baseline_rate\": child_poverty_baseline_rate,\n", + " \"child_poverty_reform_rate\": child_poverty_reform_rate,\n", + " \"child_poverty_rate_change\": child_poverty_rate_change,\n", + " \"child_poverty_percent_change\": child_poverty_percent_change,\n", + " \"deep_poverty_baseline_rate\": deep_poverty_baseline_rate,\n", + " \"deep_poverty_reform_rate\": deep_poverty_reform_rate,\n", + " \"deep_poverty_rate_change\": deep_poverty_rate_change,\n", + " \"deep_poverty_percent_change\": deep_poverty_percent_change,\n", + " \"deep_child_poverty_baseline_rate\": deep_child_poverty_baseline_rate,\n", + " \"deep_child_poverty_reform_rate\": deep_child_poverty_reform_rate,\n", + " \"deep_child_poverty_rate_change\": deep_child_poverty_rate_change,\n", + " \"deep_child_poverty_percent_change\": deep_child_poverty_percent_change,\n", + " \"by_income_bracket\": by_income_bracket,\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calculating comprehensive 2026 impacts...\n", + "Done!\n", + "2026 impact saved to reform_3_impact_2026.csv\n" + ] + } + ], + "source": [ + "# Calculate comprehensive 2026 impacts\n", + "print(\"Calculating comprehensive 2026 impacts...\")\n", + "impact_2026 = calculate_aggregate_impact(searchlight_reform, year=2026)\n", + "print(\"Done!\")\n", + "\n", + "# Export 2026 impact to CSV immediately\n", + "def export_2026_impact_to_csv(impact, filename):\n", + " \"\"\"Export the 2026 impact results to a CSV file.\"\"\"\n", + " rows = [\n", + " [\"Metric\", \"Value\"],\n", + " [\"Budgetary Impact ($)\", impact['budget']['budgetary_impact']],\n", + " [\"Total Cost ($)\", impact['total_cost']],\n", + " [\"Total Households\", impact['budget']['households']],\n", + " [\"Winners\", impact['winners']],\n", + " [\"Winners Rate (%)\", impact['winners_rate']],\n", + " [\"Losers\", impact['losers']],\n", + " [\"Losers Rate (%)\", impact['losers_rate']],\n", + " [\"Beneficiaries\", impact['beneficiaries']],\n", + " [\"Average Benefit ($)\", impact['avg_benefit']],\n", + " [\"Poverty Baseline Rate (%)\", impact['poverty_baseline_rate']],\n", + " [\"Poverty Reform Rate (%)\", impact['poverty_reform_rate']],\n", + " [\"Poverty Rate Change (pp)\", impact['poverty_rate_change']],\n", + " [\"Poverty Percent Change (%)\", impact['poverty_percent_change']],\n", + " [\"Child Poverty Baseline Rate (%)\", impact['child_poverty_baseline_rate']],\n", + " [\"Child Poverty Reform Rate (%)\", impact['child_poverty_reform_rate']],\n", + " [\"Child Poverty Rate Change (pp)\", impact['child_poverty_rate_change']],\n", + " [\"Child Poverty Percent Change (%)\", impact['child_poverty_percent_change']],\n", + " [\"Deep Poverty Baseline Rate (%)\", impact['deep_poverty_baseline_rate']],\n", + " [\"Deep Poverty Reform Rate (%)\", impact['deep_poverty_reform_rate']],\n", + " [\"Deep Poverty Rate Change (pp)\", impact['deep_poverty_rate_change']],\n", + " [\"Deep Poverty Percent Change (%)\", impact['deep_poverty_percent_change']],\n", + " [\"Deep Child Poverty Baseline Rate (%)\", impact['deep_child_poverty_baseline_rate']],\n", + " [\"Deep Child Poverty Reform Rate (%)\", impact['deep_child_poverty_reform_rate']],\n", + " [\"Deep Child Poverty Rate Change (pp)\", impact['deep_child_poverty_rate_change']],\n", + " [\"Deep Child Poverty Percent Change (%)\", impact['deep_child_poverty_percent_change']],\n", + " ]\n", + " \n", + " # Add decile data\n", + " for d in range(1, 11):\n", + " rows.append([f\"Decile {d} Average Change ($)\", impact['decile']['average'][str(d)]])\n", + " rows.append([f\"Decile {d} Relative Change\", impact['decile']['relative'][str(d)]])\n", + " \n", + " # Add income bracket data\n", + " for bracket in impact['by_income_bracket']:\n", + " rows.append([f\"Bracket {bracket['bracket']} Beneficiaries\", bracket['beneficiaries']])\n", + " rows.append([f\"Bracket {bracket['bracket']} Total Cost ($)\", bracket['total_cost']])\n", + " rows.append([f\"Bracket {bracket['bracket']} Avg Benefit ($)\", bracket['avg_benefit']])\n", + " \n", + " with open(filename, 'w', newline='') as f:\n", + " writer = csv.writer(f)\n", + " writer.writerows(rows)\n", + " \n", + " print(f\"2026 impact saved to {filename}\")\n", + "\n", + "export_2026_impact_to_csv(impact_2026, \"reform_3_impact_2026.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "============================================================\n", + "BUDGET SUMMARY (2026) - Reform 3\n", + "============================================================\n", + "Budgetary Impact: $-93.47 billion\n", + "Total Cost: $93.47 billion\n", + "Total Households: 147,829,631\n" + ] + } + ], + "source": [ + "# Display budget summary\n", + "print(\"=\" * 60)\n", + "print(\"BUDGET SUMMARY (2026) - Reform 3\")\n", + "print(\"=\" * 60)\n", + "print(f\"Budgetary Impact: ${impact_2026['budget']['budgetary_impact'] / 1e9:.2f} billion\")\n", + "print(f\"Total Cost: ${impact_2026['total_cost'] / 1e9:.2f} billion\")\n", + "print(f\"Total Households: {impact_2026['budget']['households']:,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "WINNERS / LOSERS (2026)\n", + "============================================================\n", + "Winners: 45,912,148 (31.1%)\n", + "Losers: 5,854,870 (4.0%)\n", + "Beneficiaries: 45,919,433\n", + "Average Benefit (affected): $1,805.55\n" + ] + } + ], + "source": [ + "# Display winners/losers\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"WINNERS / LOSERS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"Winners: {impact_2026['winners']:,.0f} ({impact_2026['winners_rate']:.1f}%)\")\n", + "print(f\"Losers: {impact_2026['losers']:,.0f} ({impact_2026['losers_rate']:.1f}%)\")\n", + "print(f\"Beneficiaries: {impact_2026['beneficiaries']:,.0f}\")\n", + "print(f\"Average Benefit (affected): ${impact_2026['avg_benefit']:,.2f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "POVERTY IMPACTS (2026)\n", + "============================================================\n", + "\n", + "Overall Poverty:\n", + " Baseline: 23.33%\n", + " Reform: 21.68%\n", + " Change: -1.65pp (-7.1%)\n", + "\n", + "Child Poverty:\n", + " Baseline: 22.00%\n", + " Reform: 17.52%\n", + " Change: -4.47pp (-20.3%)\n", + "\n", + "Deep Poverty:\n", + " Baseline: 8.70%\n", + " Reform: 7.49%\n", + " Change: -1.21pp (-13.9%)\n", + "\n", + "Deep Child Poverty:\n", + " Baseline: 8.56%\n", + " Reform: 5.61%\n", + " Change: -2.95pp (-34.5%)\n" + ] + } + ], + "source": [ + "# Display poverty impacts\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"POVERTY IMPACTS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"\\nOverall Poverty:\")\n", + "print(f\" Baseline: {impact_2026['poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['poverty_rate_change']:+.2f}pp ({impact_2026['poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nChild Poverty:\")\n", + "print(f\" Baseline: {impact_2026['child_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['child_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['child_poverty_rate_change']:+.2f}pp ({impact_2026['child_poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nDeep Poverty:\")\n", + "print(f\" Baseline: {impact_2026['deep_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['deep_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['deep_poverty_rate_change']:+.2f}pp ({impact_2026['deep_poverty_percent_change']:+.1f}%)\")\n", + "\n", + "print(f\"\\nDeep Child Poverty:\")\n", + "print(f\" Baseline: {impact_2026['deep_child_poverty_baseline_rate']:.2f}%\")\n", + "print(f\" Reform: {impact_2026['deep_child_poverty_reform_rate']:.2f}%\")\n", + "print(f\" Change: {impact_2026['deep_child_poverty_rate_change']:+.2f}pp ({impact_2026['deep_child_poverty_percent_change']:+.1f}%)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "DECILE ANALYSIS (2026)\n", + "============================================================\n", + "Decile Avg Change Relative Change\n", + "---------------------------------------------\n", + "1 $ 707 6.13%\n", + "2 $ 723 2.70%\n", + "3 $ 621 1.55%\n", + "4 $ 924 1.70%\n", + "5 $ 1,105 1.57%\n", + "6 $ 666 0.77%\n", + "7 $ 583 0.53%\n", + "8 $ 513 0.35%\n", + "9 $ 197 0.10%\n", + "10 $ 94 0.01%\n" + ] + } + ], + "source": [ + "# Display decile analysis\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"DECILE ANALYSIS (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"{'Decile':<10} {'Avg Change':>15} {'Relative Change':>18}\")\n", + "print(\"-\" * 45)\n", + "for d in range(1, 11):\n", + " avg = impact_2026['decile']['average'][str(d)]\n", + " rel = impact_2026['decile']['relative'][str(d)] * 100\n", + " print(f\"{d:<10} ${avg:>14,.0f} {rel:>17.2f}%\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "INCOME BRACKET BREAKDOWN (2026)\n", + "============================================================\n", + "Bracket Beneficiaries Total Cost Avg Benefit\n", + "------------------------------------------------------------\n", + "Under $50k 21,366,040 $ 52.10B $ 2,438\n", + "$50k-$100k 12,473,454 $ 23.08B $ 1,850\n", + "$100k-$200k 11,135,840 $ 14.62B $ 1,313\n", + "$200k-$500k 5,446,002 $ 0.39B $ 71\n", + "$500k-$1M 335,220 $ 0.50B $ 1,490\n", + "$1M-$2M 31,084 $ 0.02B $ 694\n", + "Over $2M 8,306 $ 0.01B $ 961\n" + ] + } + ], + "source": [ + "# Display income bracket breakdown\n", + "print(\"\\n\" + \"=\" * 60)\n", + "print(\"INCOME BRACKET BREAKDOWN (2026)\")\n", + "print(\"=\" * 60)\n", + "print(f\"{'Bracket':<15} {'Beneficiaries':>15} {'Total Cost':>15} {'Avg Benefit':>12}\")\n", + "print(\"-\" * 60)\n", + "for bracket in impact_2026['by_income_bracket']:\n", + " print(f\"{bracket['bracket']:<15} {bracket['beneficiaries']:>15,.0f} ${bracket['total_cost']/1e9:>13.2f}B ${bracket['avg_benefit']:>10,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "#105293" + }, + "text": [ + "$707", + "$723", + "$621", + "$924", + "$1,105", + "$666", + "$583", + "$513", + "$197", + "$94" + ], + "textposition": "auto", + "type": "bar", + "x": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ], + "y": [ + 706.8697119537609, + 722.7084659535038, + 621.3751652670277, + 923.8222663846096, + 1104.8989530609172, + 665.7931151242624, + 582.9788289699934, + 513.3678010209588, + 197.21083161046175, + 93.91950050668866 + ] + } + ], + "layout": { + "font": { + "color": "black", + "family": "Roboto Serif" + }, + "height": 600, + "images": [ + { + "sizex": 0.15, + "sizey": 0.15, + "source": "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png", + "x": 1.1, + "xanchor": "right", + "xref": "paper", + "y": -0.15, + "yanchor": "bottom", + "yref": "paper" + } + ], + "modebar": { + "bgcolor": "rgba(0,0,0,0)", + "color": "rgba(0,0,0,0)" + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "white", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "#C8D4E3", + "linecolor": "#C8D4E3", + "minorgridcolor": "#C8D4E3", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "white", + "showlakes": true, + "showland": true, + "subunitcolor": "#C8D4E3" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "white", + "polar": { + "angularaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + }, + "bgcolor": "white", + "radialaxis": { + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "yaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + }, + "zaxis": { + "backgroundcolor": "white", + "gridcolor": "#DFE8F3", + "gridwidth": 2, + "linecolor": "#EBF0F8", + "showbackground": true, + "ticks": "", + "zerolinecolor": "#EBF0F8" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "baxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + }, + "bgcolor": "white", + "caxis": { + "gridcolor": "#DFE8F3", + "linecolor": "#A2B1C6", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "#EBF0F8", + "linecolor": "#EBF0F8", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "#EBF0F8", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Average Income Change by Decile (2026) - Reform 3" + }, + "width": 800, + "xaxis": { + "tickmode": "linear", + "title": { + "text": "Income Decile" + } + }, + "yaxis": { + "title": { + "text": "Average Change ($)" + } + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Create decile bar chart\n", + "deciles = list(range(1, 11))\n", + "avg_changes = [impact_2026['decile']['average'][str(d)] for d in deciles]\n", + "\n", + "fig = go.Figure(\n", + " go.Bar(\n", + " x=deciles,\n", + " y=avg_changes,\n", + " text=[f\"${v:,.0f}\" for v in avg_changes],\n", + " textposition=\"auto\",\n", + " marker_color=\"#105293\",\n", + " )\n", + ")\n", + "\n", + "fig.update_layout(\n", + " title=\"Average Income Change by Decile (2026) - Reform 3\",\n", + " xaxis_title=\"Income Decile\",\n", + " yaxis_title=\"Average Change ($)\",\n", + " xaxis=dict(tickmode=\"linear\"),\n", + ")\n", + "\n", + "format_fig(fig).show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 10-Year Federal Budgetary Impact (2026-2035)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_budgetary_impact(reform, year):\n", + " \"\"\"Calculate just the federal income tax budgetary impact for a single year.\"\"\"\n", + " baseline = Microsimulation(dataset=DATASET)\n", + " reformed = Microsimulation(reform=reform, dataset=DATASET)\n", + " \n", + " baseline_income_tax = baseline.calculate(\"income_tax\", period=year).sum()\n", + " reformed_income_tax = reformed.calculate(\"income_tax\", period=year).sum()\n", + " \n", + " # Budgetary impact: negative means costs money (reform reduces tax revenue)\n", + " impact = reformed_income_tax - baseline_income_tax\n", + " return float(impact)\n", + "\n", + "\n", + "def calculate_ten_year_projection(reform, csv_filename=\"reform_3_10year_budgetary_impact.csv\"):\n", + " results = []\n", + "\n", + " with open(csv_filename, \"w\", newline=\"\") as csvfile:\n", + " csvwriter = csv.writer(csvfile)\n", + " csvwriter.writerow([\"Year\", \"Budgetary Impact\"])\n", + "\n", + " for year in range(2026, 2036):\n", + " print(f\"Computing budgetary impact for year {year}...\")\n", + " impact = calculate_budgetary_impact(reform, year)\n", + " results.append({\"Year\": year, \"Budgetary Impact\": impact})\n", + "\n", + " csvwriter.writerow([year, impact])\n", + " print(f\"Year {year} completed. Impact: ${impact/1e9:.2f} billion\")\n", + "\n", + " print(f\"All calculations complete. Results saved to '{csv_filename}'\")\n", + " return pd.DataFrame(results)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Xet Storage is enabled for this repo, but the 'hf_xet' package is not installed. Falling back to regular HTTP download. For better performance, install the package with: `pip install huggingface_hub[hf_xet]` or `pip install hf_xet`\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting 10-year budgetary impact calculation...\n", + "Computing budgetary impact for year 2026...\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "88fec242b41e4a8081ec0dea015d08f1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "enhanced_cps_2024.h5: 0%| | 0.00/111M [00:00