diff --git a/obbba_district_impacts/Congressional-Hackathon-2025 b/obbba_district_impacts/Congressional-Hackathon-2025 new file mode 160000 index 0000000..3f6d05e --- /dev/null +++ b/obbba_district_impacts/Congressional-Hackathon-2025 @@ -0,0 +1 @@ +Subproject commit 3f6d05e76400c6e396a3a4eddd34a7b3f6919fc3 diff --git a/us/states/ut/data_exploration.ipynb b/us/states/ut/data_exploration.ipynb new file mode 100644 index 0000000..add646c --- /dev/null +++ b/us/states/ut/data_exploration.ipynb @@ -0,0 +1,422 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# UT Dataset Exploration\n", + "\n", + "This notebook explores the Utah (UT) dataset to understand household counts, income distribution, and demographic characteristics." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "UT_DATASET = \"hf://policyengine/policyengine-us-data/states/UT.h5\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "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" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "348889a2464c4fd8bf369b4288fa9b00", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "UT.h5: 0%| | 0.00/39.1M [00:00 0]['household_weight'].sum()\n", + "households_with_1_child = children_per_household[children_per_household['is_child'] == 1]['household_weight'].sum()\n", + "households_with_2_children = children_per_household[children_per_household['is_child'] == 2]['household_weight'].sum()\n", + "households_with_3plus_children = children_per_household[children_per_household['is_child'] >= 3]['household_weight'].sum()\n", + "\n", + "print(f\"\\nHouseholds with children (weighted):\")\n", + "print(f\" Total households with children: {total_households_with_children:,.0f}\")\n", + "print(f\" Households with 1 child: {households_with_1_child:,.0f}\")\n", + "print(f\" Households with 2 children: {households_with_2_children:,.0f}\")\n", + "print(f\" Households with 3+ children: {households_with_3plus_children:,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Children by age:\n", + " Total children under 18: 931,582\n", + " Children under 6: 276,080\n", + " Children under 3: 120,763\n" + ] + } + ], + "source": [ + "# Check children by age groups\n", + "df = pd.DataFrame({\n", + " \"household_id\": sim.calculate(\"household_id\", map_to=\"person\"),\n", + " \"tax_unit_id\": sim.calculate(\"tax_unit_id\", map_to=\"person\"),\n", + " \"person_id\": sim.calculate(\"person_id\", map_to=\"person\"),\n", + " \"age\": sim.calculate(\"age\", map_to=\"person\"),\n", + " \"person_weight\": sim.calculate(\"person_weight\", map_to=\"person\")\n", + "})\n", + "\n", + "# Filter for children and apply weights\n", + "children_under_18_df = df[df['age'] < 18]\n", + "children_under_6_df = df[df['age'] < 6]\n", + "children_under_3_df = df[df['age'] < 3]\n", + "\n", + "# Calculate weighted totals\n", + "total_children = children_under_18_df['person_weight'].sum()\n", + "children_under_6 = children_under_6_df['person_weight'].sum()\n", + "children_under_3 = children_under_3_df['person_weight'].sum()\n", + "\n", + "print(f\"\\nChildren by age:\")\n", + "print(f\" Total children under 18: {total_children:,.0f}\")\n", + "print(f\" Children under 6: {children_under_6:,.0f}\")\n", + "print(f\" Children under 3: {children_under_3:,.0f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "============================================================\n", + "UT DATASET SUMMARY - WEIGHTED (Population Estimates)\n", + "============================================================\n", + " Metric Value\n", + " Household count (weighted) 1,015,265\n", + " Person count (weighted) 3,467,711\n", + " Median AGI $104,469\n", + " 75th percentile AGI $214,444\n", + " 90th percentile AGI $432,171\n", + " 95th percentile AGI $541,148\n", + " Max AGI $3,229,514\n", + "Total households with children 452,300\n", + " Households with 1 child 167,413\n", + " Households with 2 children 159,249\n", + " Households with 3+ children 125,638\n", + " Total children under 18 931,582\n", + " Children under 6 276,080\n", + " Children under 3 120,763\n", + "============================================================\n", + "\n", + "Summary saved to: ut_dataset_summary_weighted.csv\n" + ] + }, + { + "ename": "", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31mThe Kernel crashed while executing code in the current cell or a previous cell. \n", + "\u001b[1;31mPlease review the code in the cell(s) to identify a possible cause of the failure. \n", + "\u001b[1;31mClick here for more info. \n", + "\u001b[1;31mView Jupyter log for further details." + ] + } + ], + "source": [ + "# Create weighted summary table\n", + "weighted_summary_data = {\n", + " 'Metric': [\n", + " 'Household count (weighted)',\n", + " 'Person count (weighted)',\n", + " 'Median AGI',\n", + " '75th percentile AGI',\n", + " '90th percentile AGI',\n", + " '95th percentile AGI',\n", + " 'Max AGI',\n", + " 'Total households with children',\n", + " 'Households with 1 child',\n", + " 'Households with 2 children',\n", + " 'Households with 3+ children',\n", + " 'Total children under 18',\n", + " 'Children under 6',\n", + " 'Children under 3'\n", + " ],\n", + " 'Value': [\n", + " f\"{household_count.sum():,.0f}\",\n", + " f\"{person_count.sum():,.0f}\",\n", + " f\"${agi.median():,.0f}\",\n", + " f\"${agi.quantile(0.75):,.0f}\",\n", + " f\"${agi.quantile(0.90):,.0f}\",\n", + " f\"${agi.quantile(0.95):,.0f}\",\n", + " f\"${agi.max():,.0f}\",\n", + " f\"{total_households_with_children:,.0f}\",\n", + " f\"{households_with_1_child:,.0f}\",\n", + " f\"{households_with_2_children:,.0f}\",\n", + " f\"{households_with_3plus_children:,.0f}\",\n", + " f\"{total_children:,.0f}\",\n", + " f\"{children_under_6:,.0f}\",\n", + " f\"{children_under_3:,.0f}\"\n", + " ]\n", + "}\n", + "\n", + "weighted_df = pd.DataFrame(weighted_summary_data)\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"UT DATASET SUMMARY - WEIGHTED (Population Estimates)\")\n", + "print(\"=\"*60)\n", + "print(weighted_df.to_string(index=False))\n", + "print(\"=\"*60)\n", + "\n", + "# Save table\n", + "weighted_df.to_csv('ut_dataset_summary_weighted.csv', index=False)\n", + "print(\"\\nSummary saved to: ut_dataset_summary_weighted.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "======================================================================\n", + "HOUSEHOLDS WITH $0 INCOME\n", + "======================================================================\n", + "Household count: 48,395\n", + "Percentage of all households: 4.77%\n", + "======================================================================\n" + ] + } + ], + "source": [ + "# Households with $0 income\n", + "agi_hh = np.array(sim.calculate(\"adjusted_gross_income\", period=2025, map_to=\"household\"))\n", + "weights = np.array(sim.calculate(\"household_weight\", period=2025))\n", + "\n", + "zero_income_mask = agi_hh == 0\n", + "zero_income_count = weights[zero_income_mask].sum()\n", + "total_households = weights.sum()\n", + "\n", + "print(\"\\n\" + \"=\"*70)\n", + "print(\"HOUSEHOLDS WITH $0 INCOME\")\n", + "print(\"=\"*70)\n", + "print(f\"Household count: {zero_income_count:,.0f}\")\n", + "print(f\"Percentage of all households: {zero_income_count / total_households * 100:.2f}%\")\n", + "print(\"=\"*70)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "======================================================================\n", + "HOUSEHOLD COUNTS BY INCOME BRACKET\n", + "======================================================================\n", + "Income Bracket Households % of All Households\n", + " $0-$10k 126,445 12.45%\n", + " $10k-$20k 15,102 1.49%\n", + " $20k-$30k 21,610 2.13%\n", + " $30k-$40k 71,543 7.05%\n", + " $40k-$50k 62,599 6.17%\n", + " $50k-$60k 40,115 3.95%\n", + "======================================================================\n", + "\n", + "Total households in $0-$60k range: 337,414\n", + "Percentage of all households in $0-$60k range: 33.23%\n" + ] + } + ], + "source": [ + "# Household counts by income brackets\n", + "income_brackets = [\n", + " (0, 10000, \"$0-$10k\"),\n", + " (10000, 20000, \"$10k-$20k\"),\n", + " (20000, 30000, \"$20k-$30k\"),\n", + " (30000, 40000, \"$30k-$40k\"),\n", + " (40000, 50000, \"$40k-$50k\"),\n", + " (50000, 60000, \"$50k-$60k\")\n", + "]\n", + "\n", + "bracket_data = []\n", + "for lower, upper, label in income_brackets:\n", + " mask = (agi_hh >= lower) & (agi_hh < upper)\n", + " count = weights[mask].sum()\n", + " pct_of_total = (count / total_households) * 100\n", + " \n", + " bracket_data.append({\n", + " \"Income Bracket\": label,\n", + " \"Households\": f\"{count:,.0f}\",\n", + " \"% of All Households\": f\"{pct_of_total:.2f}%\"\n", + " })\n", + "\n", + "income_df = pd.DataFrame(bracket_data)\n", + "\n", + "print(\"\\n\" + \"=\"*70)\n", + "print(\"HOUSEHOLD COUNTS BY INCOME BRACKET\")\n", + "print(\"=\"*70)\n", + "print(income_df.to_string(index=False))\n", + "print(\"=\"*70)\n", + "\n", + "# Total in $0-$60k range\n", + "total_in_range = sum([weights[(agi_hh >= lower) & (agi_hh < upper)].sum() for lower, upper, _ in income_brackets])\n", + "print(f\"\\nTotal households in $0-$60k range: {total_in_range:,.0f}\")\n", + "print(f\"Percentage of all households in $0-$60k range: {total_in_range / total_households * 100:.2f}%\")" + ] + } + ], + "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/states/ut/ut_ctc_reform_analysis.ipynb b/us/states/ut/ut_ctc_reform_analysis.ipynb new file mode 100644 index 0000000..6c6e77e --- /dev/null +++ b/us/states/ut/ut_ctc_reform_analysis.ipynb @@ -0,0 +1,518 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Utah CTC Reform Analysis (2025)\n", + "\n", + "This notebook analyzes the impact of modifying Utah's Child Tax Credit (CTC) reduction start thresholds.\n", + "\n", + "## Baseline (Current Law)\n", + "- Utah CTC phases out at lower income thresholds\n", + "\n", + "## Reform\n", + "- Increase the CTC reduction start thresholds:\n", + " - Joint: $59,000\n", + " - Single: $48,000\n", + " - Separate: $29,500\n", + " - Surviving Spouse: $59,000\n", + " - Head of Household: $48,000\n", + "\n", + "## Metrics\n", + "We calculate:\n", + "- Budgetary impact (net cost)\n", + "- Winners (percentage of population affected)\n", + "- Overall poverty impact\n", + "- Child poverty impact" + ] + }, + { + "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", + "\n", + "UT_DATASET = \"hf://policyengine/policyengine-us-data/states/UT.h5\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper Functions" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_poverty(sim, period=2025, child_only=False):\n", + " \"\"\"\n", + " Calculate poverty rate and count.\n", + " \n", + " Args:\n", + " sim: Microsimulation object\n", + " period: Year to analyze\n", + " child_only: If True, only count children under 18\n", + " \n", + " Returns:\n", + " poverty_rate: Weighted poverty rate\n", + " people_in_poverty: Weighted count\n", + " \"\"\"\n", + " age = np.array(sim.calculate(\"age\", period=period))\n", + " is_in_poverty = np.array(sim.calculate(\"person_in_poverty\", period=period))\n", + " person_weight = np.array(sim.calculate(\"person_weight\", period=period))\n", + " \n", + " if child_only:\n", + " mask = age < 18\n", + " else:\n", + " mask = np.ones_like(age, dtype=bool)\n", + " \n", + " # Weighted poverty rate\n", + " weighted_in_poverty = (is_in_poverty[mask] * person_weight[mask]).sum()\n", + " weighted_total = person_weight[mask].sum()\n", + " poverty_rate = weighted_in_poverty / weighted_total if weighted_total > 0 else 0\n", + " \n", + " # Weighted count of people in poverty\n", + " people_in_poverty = weighted_in_poverty\n", + " \n", + " return {\n", + " \"poverty_rate\": poverty_rate,\n", + " \"people_in_poverty\": people_in_poverty,\n", + " \"total_people\": weighted_total\n", + " }\n", + "\n", + "def calculate_budgetary_impact(baseline_sim, reform_sim, variable, period=2025):\n", + " \"\"\"\n", + " Calculate the budgetary impact (net cost) of a reform.\n", + " \"\"\"\n", + " baseline_value = baseline_sim.calculate(variable, period=period, map_to=\"household\").sum()\n", + " reform_value = reform_sim.calculate(variable, period=period, map_to=\"household\").sum()\n", + " \n", + " return reform_value - baseline_value\n", + "\n", + "def calculate_winners(baseline_sim, reform_sim, period=2025):\n", + " \"\"\"\n", + " Calculate winners from a reform at the person level (weighted).\n", + " Winners: People in households with higher net income under reform.\n", + " Returns weighted count and percentage of total population.\n", + " \"\"\"\n", + " # Get household-level income change\n", + " baseline_income = np.array(baseline_sim.calculate(\"household_net_income\", period=period, map_to=\"household\"))\n", + " reform_income = np.array(reform_sim.calculate(\"household_net_income\", period=period, map_to=\"household\"))\n", + " household_weight = np.array(baseline_sim.calculate(\"household_weight\", period=period))\n", + " income_change = reform_income - baseline_income\n", + " \n", + " # Get person-level data\n", + " household_id_person = np.array(baseline_sim.calculate(\"household_id\", period=period, map_to=\"person\"))\n", + " household_id_household = np.array(baseline_sim.calculate(\"household_id\", period=period, map_to=\"household\"))\n", + " person_weight = np.array(baseline_sim.calculate(\"person_weight\", period=period))\n", + " \n", + " # Create mapping of household_id to income_change\n", + " income_change_dict = dict(zip(household_id_household, income_change))\n", + " \n", + " # Map income change to each person\n", + " person_income_change = np.array([income_change_dict.get(hh_id, 0) for hh_id in household_id_person])\n", + " \n", + " # Weighted count of people who are winners (gained more than $1)\n", + " winners_mask = person_income_change > 1\n", + " people_winning = person_weight[winners_mask].sum()\n", + " total_people = person_weight.sum()\n", + " \n", + " # Calculate percentage\n", + " pct_winners = (people_winning / total_people * 100) if total_people > 0 else 0\n", + " \n", + " # Average gain for winning households (weighted)\n", + " winning_hh_mask = income_change > 1\n", + " if winning_hh_mask.sum() > 0:\n", + " avg_gain = np.average(income_change[winning_hh_mask], weights=household_weight[winning_hh_mask])\n", + " else:\n", + " avg_gain = 0\n", + " \n", + " return {\n", + " \"people_winning\": people_winning,\n", + " \"total_people\": total_people,\n", + " \"pct_winners\": pct_winners,\n", + " \"avg_gain\": avg_gain\n", + " }\n", + "\n", + "def format_currency(value):\n", + " \"\"\"Format value as currency in millions.\"\"\"\n", + " return f\"${value/1e6:.2f}M\"\n", + "\n", + "def format_percent(value):\n", + " \"\"\"Format value as percentage.\"\"\"\n", + " return f\"{value*100:.2f}%\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define Baseline and Reform" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform function defined!\n" + ] + } + ], + "source": [ + "def create_ctc_reform():\n", + " \"\"\"Reform: Modify Utah CTC reduction start thresholds\"\"\"\n", + " reform = Reform.from_dict(\n", + " {\n", + " \"gov.states.ut.tax.income.credits.ctc.reduction.start.JOINT\": {\n", + " \"2025-01-01.2100-12-31\": 59000\n", + " },\n", + " \"gov.states.ut.tax.income.credits.ctc.reduction.start.SINGLE\": {\n", + " \"2025-01-01.2100-12-31\": 48000\n", + " },\n", + " \"gov.states.ut.tax.income.credits.ctc.reduction.start.SEPARATE\": {\n", + " \"2025-01-01.2100-12-31\": 29500\n", + " },\n", + " \"gov.states.ut.tax.income.credits.ctc.reduction.start.SURVIVING_SPOUSE\": {\n", + " \"2025-01-01.2100-12-31\": 59000\n", + " },\n", + " \"gov.states.ut.tax.income.credits.ctc.reduction.start.HEAD_OF_HOUSEHOLD\": {\n", + " \"2025-01-01.2100-12-31\": 48000\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + " return reform\n", + "\n", + "print(\"Reform function defined!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load Simulations" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading baseline (current law - existing UT CTC thresholds)...\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": "4800beb926e6478dba5cabaf93483ef4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "UT.h5: 0%| | 0.00/39.1M [00:00 0 else 0\n", + "print(f\"Absolute reduction: {format_percent(overall_pov_reduction)}\")\n", + "print(f\"Relative reduction: {overall_pov_pct_reduction:.2f}%\")\n", + "people_lifted = baseline_overall_pov['people_in_poverty'] - reform_overall_pov['people_in_poverty']\n", + "print(f\"People lifted from poverty: {people_lifted:,.0f}\")\n", + "\n", + "print(f\"\\n{'POVERTY IMPACT - CHILDREN':=^80}\")\n", + "print(f\"Baseline child poverty rate: {format_percent(baseline_child_pov['poverty_rate'])}\")\n", + "print(f\"Reform child poverty rate: {format_percent(reform_child_pov['poverty_rate'])}\")\n", + "child_pov_reduction = baseline_child_pov['poverty_rate'] - reform_child_pov['poverty_rate']\n", + "child_pov_pct_reduction = (child_pov_reduction / baseline_child_pov['poverty_rate'] * 100) if baseline_child_pov['poverty_rate'] > 0 else 0\n", + "print(f\"Absolute reduction: {format_percent(child_pov_reduction)}\")\n", + "print(f\"Relative reduction: {child_pov_pct_reduction:.2f}%\")\n", + "children_lifted = baseline_child_pov['people_in_poverty'] - reform_child_pov['people_in_poverty']\n", + "print(f\"Children lifted from poverty: {children_lifted:,.0f}\")\n", + "print(\"=\"*80)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "HOUSEHOLDS BENEFITTING FROM UT CTC REFORM\n", + "======================================================================\n", + "Households benefitting: 25,237\n", + "Total households: 1,015,265\n", + "Percentage of households: 2.49%\n", + "======================================================================\n" + ] + } + ], + "source": [ + "# Calculate households benefitting (weighted)\n", + "baseline_hh_income = np.array(baseline.calculate(\"household_net_income\", period=2025, map_to=\"household\"))\n", + "reform_hh_income = np.array(reform_sim.calculate(\"household_net_income\", period=2025, map_to=\"household\"))\n", + "household_weight = np.array(baseline.calculate(\"household_weight\", period=2025))\n", + "\n", + "hh_income_change = reform_hh_income - baseline_hh_income\n", + "hh_benefitting_mask = hh_income_change > 1 # Gained more than $1\n", + "\n", + "households_benefitting = household_weight[hh_benefitting_mask].sum()\n", + "total_households = household_weight.sum()\n", + "pct_households_benefitting = (households_benefitting / total_households) * 100\n", + "\n", + "print(\"=\"*70)\n", + "print(\"HOUSEHOLDS BENEFITTING FROM UT CTC REFORM\")\n", + "print(\"=\"*70)\n", + "print(f\"Households benefitting: {households_benefitting:,.0f}\")\n", + "print(f\"Total households: {total_households:,.0f}\")\n", + "print(f\"Percentage of households: {pct_households_benefitting:.2f}%\")\n", + "print(\"=\"*70)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Export Results" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "==============================================================================================================\n", + "UT CTC REFORM SUMMARY\n", + "==============================================================================================================\n", + " Scenario Description Net Cost Overall Poverty Change (%) Child Poverty Change (%) % Population Winning\n", + "CTC Reform Increased CTC reduction start thresholds $10.08M 0.00% 0.00% 3.93%\n", + "==============================================================================================================\n", + "\n", + "Exported to: ut_ctc_reform_results.csv\n" + ] + } + ], + "source": [ + "# Calculate poverty changes\n", + "overall_pov_reduction = baseline_overall_pov['poverty_rate'] - reform_overall_pov['poverty_rate']\n", + "overall_pov_pct_reduction = (overall_pov_reduction / baseline_overall_pov['poverty_rate'] * 100) if baseline_overall_pov['poverty_rate'] > 0 else 0\n", + "child_pov_reduction = baseline_child_pov['poverty_rate'] - reform_child_pov['poverty_rate']\n", + "child_pov_pct_reduction = (child_pov_reduction / baseline_child_pov['poverty_rate'] * 100) if baseline_child_pov['poverty_rate'] > 0 else 0\n", + "\n", + "# Create results DataFrame (reform only)\n", + "results = [\n", + " {\n", + " \"Scenario\": \"CTC Reform\",\n", + " \"Description\": \"Increased CTC reduction start thresholds\",\n", + " \"Net Cost\": format_currency(ctc_cost),\n", + " \"Overall Poverty Change (%)\": f\"{overall_pov_pct_reduction:.2f}%\",\n", + " \"Child Poverty Change (%)\": f\"{child_pov_pct_reduction:.2f}%\",\n", + " \"% Population Winning\": f\"{winners['pct_winners']:.2f}%\"\n", + " }\n", + "]\n", + "\n", + "df_results = pd.DataFrame(results)\n", + "\n", + "print(\"\\n\" + \"=\"*110)\n", + "print(\"UT CTC REFORM SUMMARY\")\n", + "print(\"=\"*110)\n", + "print(df_results.to_string(index=False))\n", + "print(\"=\"*110)\n", + "\n", + "# Export to CSV\n", + "df_results.to_csv(\"ut_ctc_reform_results.csv\", index=False)\n", + "print(\"\\nExported to: ut_ctc_reform_results.csv\")" + ] + } + ], + "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/states/ut/ut_ctc_reform_results.csv b/us/states/ut/ut_ctc_reform_results.csv new file mode 100644 index 0000000..cd793ce --- /dev/null +++ b/us/states/ut/ut_ctc_reform_results.csv @@ -0,0 +1,2 @@ +Scenario,Description,Net Cost,Overall Poverty Change (%),Child Poverty Change (%),% Population Winning +CTC Reform,Increased CTC reduction start thresholds,$10.08M,0.00%,0.00%,3.93% diff --git a/us/states/ut/ut_dataset_summary_weighted.csv b/us/states/ut/ut_dataset_summary_weighted.csv new file mode 100644 index 0000000..71d2eac --- /dev/null +++ b/us/states/ut/ut_dataset_summary_weighted.csv @@ -0,0 +1,15 @@ +Metric,Value +Household count (weighted),"1,015,265" +Person count (weighted),"3,467,711" +Median AGI,"$104,469" +75th percentile AGI,"$214,444" +90th percentile AGI,"$432,171" +95th percentile AGI,"$541,148" +Max AGI,"$3,229,514" +Total households with children,"452,300" +Households with 1 child,"167,413" +Households with 2 children,"159,249" +Households with 3+ children,"125,638" +Total children under 18,"931,582" +Children under 6,"276,080" +Children under 3,"120,763" diff --git a/us/states/ut/ut_eitc_reform_analysis.ipynb b/us/states/ut/ut_eitc_reform_analysis.ipynb new file mode 100644 index 0000000..953cd25 --- /dev/null +++ b/us/states/ut/ut_eitc_reform_analysis.ipynb @@ -0,0 +1,489 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Utah EITC Reform Analysis (2025)\n", + "\n", + "This notebook analyzes the impact of making Utah's Earned Income Tax Credit (EITC) refundable for families with young children.\n", + "\n", + "## Baseline (Current Law)\n", + "- Utah EITC matches 20% of the federal EITC\n", + "- The credit is non-refundable\n", + "\n", + "## Reform\n", + "- Make the Utah EITC fully refundable for households with children age 2 or younger\n", + "\n", + "## Metrics\n", + "We calculate:\n", + "- Budgetary impact (net cost)\n", + "- Winners (percentage of population affected)\n", + "- Overall poverty impact\n", + "- Child poverty impact" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation\n", + "from policyengine_core.reforms import Reform\n", + "from policyengine_us.reforms.states.ut.ut_refundable_eitc import ut_refundable_eitc\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "UT_DATASET = \"hf://policyengine/policyengine-us-data/states/UT.h5\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Helper Functions" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_poverty(sim, period=2025, child_only=False):\n", + " \"\"\"\n", + " Calculate poverty rate and count.\n", + " \n", + " Args:\n", + " sim: Microsimulation object\n", + " period: Year to analyze\n", + " child_only: If True, only count children under 18\n", + " \n", + " Returns:\n", + " poverty_rate: Weighted poverty rate\n", + " people_in_poverty: Weighted count\n", + " \"\"\"\n", + " age = np.array(sim.calculate(\"age\", period=period))\n", + " is_in_poverty = np.array(sim.calculate(\"person_in_poverty\", period=period))\n", + " person_weight = np.array(sim.calculate(\"person_weight\", period=period))\n", + " \n", + " if child_only:\n", + " mask = age < 18\n", + " else:\n", + " mask = np.ones_like(age, dtype=bool)\n", + " \n", + " # Weighted poverty rate\n", + " weighted_in_poverty = (is_in_poverty[mask] * person_weight[mask]).sum()\n", + " weighted_total = person_weight[mask].sum()\n", + " poverty_rate = weighted_in_poverty / weighted_total if weighted_total > 0 else 0\n", + " \n", + " # Weighted count of people in poverty\n", + " people_in_poverty = weighted_in_poverty\n", + " \n", + " return {\n", + " \"poverty_rate\": poverty_rate,\n", + " \"people_in_poverty\": people_in_poverty,\n", + " \"total_people\": weighted_total\n", + " }\n", + "\n", + "def calculate_budgetary_impact(baseline_sim, reform_sim, variable, period=2025):\n", + " \"\"\"\n", + " Calculate the budgetary impact (net cost) of a reform.\n", + " \"\"\"\n", + " baseline_value = baseline_sim.calculate(variable, period=period, map_to=\"household\").sum()\n", + " reform_value = reform_sim.calculate(variable, period=period, map_to=\"household\").sum()\n", + " \n", + " return reform_value - baseline_value\n", + "\n", + "def calculate_winners(baseline_sim, reform_sim, period=2025):\n", + " \"\"\"\n", + " Calculate winners from a reform at the person level (weighted).\n", + " Winners: People in households with higher net income under reform.\n", + " Returns weighted count and percentage of total population.\n", + " \"\"\"\n", + " # Get household-level income change\n", + " baseline_income = np.array(baseline_sim.calculate(\"household_net_income\", period=period, map_to=\"household\"))\n", + " reform_income = np.array(reform_sim.calculate(\"household_net_income\", period=period, map_to=\"household\"))\n", + " household_weight = np.array(baseline_sim.calculate(\"household_weight\", period=period))\n", + " income_change = reform_income - baseline_income\n", + " \n", + " # Get person-level data\n", + " household_id_person = np.array(baseline_sim.calculate(\"household_id\", period=period, map_to=\"person\"))\n", + " household_id_household = np.array(baseline_sim.calculate(\"household_id\", period=period, map_to=\"household\"))\n", + " person_weight = np.array(baseline_sim.calculate(\"person_weight\", period=period))\n", + " \n", + " # Create mapping of household_id to income_change\n", + " income_change_dict = dict(zip(household_id_household, income_change))\n", + " \n", + " # Map income change to each person\n", + " person_income_change = np.array([income_change_dict.get(hh_id, 0) for hh_id in household_id_person])\n", + " \n", + " # Weighted count of people who are winners (gained more than $1)\n", + " winners_mask = person_income_change > 1\n", + " people_winning = person_weight[winners_mask].sum()\n", + " total_people = person_weight.sum()\n", + " \n", + " # Calculate percentage\n", + " pct_winners = (people_winning / total_people * 100) if total_people > 0 else 0\n", + " \n", + " # Average gain for winning households (weighted)\n", + " winning_hh_mask = income_change > 1\n", + " if winning_hh_mask.sum() > 0:\n", + " avg_gain = np.average(income_change[winning_hh_mask], weights=household_weight[winning_hh_mask])\n", + " else:\n", + " avg_gain = 0\n", + " \n", + " return {\n", + " \"people_winning\": people_winning,\n", + " \"total_people\": total_people,\n", + " \"pct_winners\": pct_winners,\n", + " \"avg_gain\": avg_gain\n", + " }\n", + "\n", + "def format_currency(value):\n", + " \"\"\"Format value as currency in millions.\"\"\"\n", + " return f\"${value/1e6:.2f}M\"\n", + "\n", + "def format_percent(value):\n", + " \"\"\"Format value as percentage.\"\"\"\n", + " return f\"{value*100:.2f}%\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Define Baseline and Reform" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reform functions defined!\n" + ] + } + ], + "source": [ + "def create_reform():\n", + " \"\"\"Reform: Make UT EITC refundable for households with children age 2 or younger\"\"\"\n", + " param_reform = Reform.from_dict(\n", + " {\n", + " \"gov.contrib.states.ut.eitc.in_effect\": {\n", + " \"2025-01-01.2100-12-31\": True\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + " # Combine the parameter reform with the structural reform\n", + " return (param_reform, ut_refundable_eitc)\n", + "\n", + "print(\"Reform functions defined!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load Simulations" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading baseline (current law - non-refundable UT EITC at 20%)...\n", + "Baseline loaded\n", + "\n", + "Loading reform (refundable UT EITC for families with young children)...\n", + "Reform loaded\n", + "\n", + "============================================================\n", + "All simulations ready!\n", + "============================================================\n" + ] + } + ], + "source": [ + "print(\"Loading baseline (current law - non-refundable UT EITC at 20%)...\")\n", + "baseline = Microsimulation(dataset=UT_DATASET)\n", + "print(\"Baseline loaded\")\n", + "\n", + "print(\"\\nLoading reform (refundable UT EITC for families with young children)...\")\n", + "reform = create_reform()\n", + "reform_sim = Microsimulation(dataset=UT_DATASET, reform=reform)\n", + "print(\"Reform loaded\")\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"All simulations ready!\")\n", + "print(\"=\"*60)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Impacts" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "All impacts calculated\n" + ] + } + ], + "source": [ + "# Baseline metrics\n", + "baseline_overall_pov = calculate_poverty(baseline, child_only=False)\n", + "baseline_child_pov = calculate_poverty(baseline, child_only=True)\n", + "\n", + "# Reform metrics\n", + "reform_overall_pov = calculate_poverty(reform_sim, child_only=False)\n", + "reform_child_pov = calculate_poverty(reform_sim, child_only=True)\n", + "\n", + "# Budgetary impact - calculated as increase in household net income (cost to state)\n", + "# The refundable EITC variable only exists in reform, so we use net income change\n", + "baseline_hh_income = baseline.calculate(\"household_net_income\", period=2025, map_to=\"household\").sum()\n", + "reform_hh_income = reform_sim.calculate(\"household_net_income\", period=2025, map_to=\"household\").sum()\n", + "eitc_cost = reform_hh_income - baseline_hh_income\n", + "\n", + "# Winners (at person level)\n", + "winners = calculate_winners(baseline, reform_sim)\n", + "\n", + "print(\"All impacts calculated\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Results Summary" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "================================================================================\n", + "UTAH EITC REFORM IMPACTS (2025)\n", + "Baseline: Non-refundable UT EITC at 20% | Reform: Refundable for families with children age 0-2\n", + "================================================================================\n", + "\n", + "================================BUDGETARY IMPACT================================\n", + "UT Refundable EITC net cost: $14.22M\n", + "\n", + "==============================WINNERS (POPULATION)==============================\n", + "People gaining income: 98,777 (2.85% of population)\n", + "Average gain per household: $668.61\n", + "\n", + "============================POVERTY IMPACT - OVERALL============================\n", + "Baseline poverty rate: 8.32%\n", + "Reform poverty rate: 8.04%\n", + "Absolute reduction: 0.27%\n", + "Relative reduction: 3.29%\n", + "People lifted from poverty: 9,497\n", + "\n", + "===========================POVERTY IMPACT - CHILDREN============================\n", + "Baseline child poverty rate: 6.37%\n", + "Reform child poverty rate: 5.87%\n", + "Absolute reduction: 0.50%\n", + "Relative reduction: 7.84%\n", + "Children lifted from poverty: 4,749\n", + "================================================================================\n" + ] + } + ], + "source": [ + "print(\"\\n\" + \"=\"*80)\n", + "print(\"UTAH EITC REFORM IMPACTS (2025)\")\n", + "print(\"Baseline: Non-refundable UT EITC at 20% | Reform: Refundable for families with children age 0-2\")\n", + "print(\"=\"*80)\n", + "\n", + "print(f\"\\n{'BUDGETARY IMPACT':=^80}\")\n", + "print(f\"UT Refundable EITC net cost: {format_currency(eitc_cost)}\")\n", + "\n", + "print(f\"\\n{'WINNERS (POPULATION)':=^80}\")\n", + "print(f\"People gaining income: {winners['people_winning']:,.0f} ({winners['pct_winners']:.2f}% of population)\")\n", + "print(f\"Average gain per household: ${winners['avg_gain']:,.2f}\")\n", + "\n", + "print(f\"\\n{'POVERTY IMPACT - OVERALL':=^80}\")\n", + "print(f\"Baseline poverty rate: {format_percent(baseline_overall_pov['poverty_rate'])}\")\n", + "print(f\"Reform poverty rate: {format_percent(reform_overall_pov['poverty_rate'])}\")\n", + "overall_pov_reduction = baseline_overall_pov['poverty_rate'] - reform_overall_pov['poverty_rate']\n", + "overall_pov_pct_reduction = (overall_pov_reduction / baseline_overall_pov['poverty_rate'] * 100) if baseline_overall_pov['poverty_rate'] > 0 else 0\n", + "print(f\"Absolute reduction: {format_percent(overall_pov_reduction)}\")\n", + "print(f\"Relative reduction: {overall_pov_pct_reduction:.2f}%\")\n", + "people_lifted = baseline_overall_pov['people_in_poverty'] - reform_overall_pov['people_in_poverty']\n", + "print(f\"People lifted from poverty: {people_lifted:,.0f}\")\n", + "\n", + "print(f\"\\n{'POVERTY IMPACT - CHILDREN':=^80}\")\n", + "print(f\"Baseline child poverty rate: {format_percent(baseline_child_pov['poverty_rate'])}\")\n", + "print(f\"Reform child poverty rate: {format_percent(reform_child_pov['poverty_rate'])}\")\n", + "child_pov_reduction = baseline_child_pov['poverty_rate'] - reform_child_pov['poverty_rate']\n", + "child_pov_pct_reduction = (child_pov_reduction / baseline_child_pov['poverty_rate'] * 100) if baseline_child_pov['poverty_rate'] > 0 else 0\n", + "print(f\"Absolute reduction: {format_percent(child_pov_reduction)}\")\n", + "print(f\"Relative reduction: {child_pov_pct_reduction:.2f}%\")\n", + "children_lifted = baseline_child_pov['people_in_poverty'] - reform_child_pov['people_in_poverty']\n", + "print(f\"Children lifted from poverty: {children_lifted:,.0f}\")\n", + "print(\"=\"*80)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "HOUSEHOLDS BENEFITTING FROM UT REFUNDABLE EITC\n", + "======================================================================\n", + "Households benefitting: 21,262\n", + "Total households: 1,015,265\n", + "Percentage of households: 2.09%\n", + "======================================================================\n" + ] + } + ], + "source": [ + "# Calculate households benefitting (weighted)\n", + "baseline_hh_income = np.array(baseline.calculate(\"household_net_income\", period=2025, map_to=\"household\"))\n", + "reform_hh_income = np.array(reform_sim.calculate(\"household_net_income\", period=2025, map_to=\"household\"))\n", + "household_weight = np.array(baseline.calculate(\"household_weight\", period=2025))\n", + "\n", + "hh_income_change = reform_hh_income - baseline_hh_income\n", + "hh_benefitting_mask = hh_income_change > 1 # Gained more than $1\n", + "\n", + "households_benefitting = household_weight[hh_benefitting_mask].sum()\n", + "total_households = household_weight.sum()\n", + "pct_households_benefitting = (households_benefitting / total_households) * 100\n", + "\n", + "print(\"=\"*70)\n", + "print(\"HOUSEHOLDS BENEFITTING FROM UT REFUNDABLE EITC\")\n", + "print(\"=\"*70)\n", + "print(f\"Households benefitting: {households_benefitting:,.0f}\")\n", + "print(f\"Total households: {total_households:,.0f}\")\n", + "print(f\"Percentage of households: {pct_households_benefitting:.2f}%\")\n", + "print(\"=\"*70)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Export Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "==============================================================================================================\n", + "UT EITC REFORM SUMMARY\n", + "==============================================================================================================\n", + "Scenario Description Net Cost Overall Poverty Change (%) Child Poverty Change (%) % Population Winning\n", + " Reform Refundable EITC for children age 0-2 $14.22M 3.29% 7.84% 2.85%\n", + "==============================================================================================================\n", + "\n", + "Exported to: ut_eitc_reform_results.csv\n" + ] + }, + { + "ename": "", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31mThe Kernel crashed while executing code in the current cell or a previous cell. \n", + "\u001b[1;31mPlease review the code in the cell(s) to identify a possible cause of the failure. \n", + "\u001b[1;31mClick here for more info. \n", + "\u001b[1;31mView Jupyter log for further details." + ] + } + ], + "source": [ + "# Calculate poverty changes\n", + "overall_pov_reduction = baseline_overall_pov['poverty_rate'] - reform_overall_pov['poverty_rate']\n", + "overall_pov_pct_reduction = (overall_pov_reduction / baseline_overall_pov['poverty_rate'] * 100) if baseline_overall_pov['poverty_rate'] > 0 else 0\n", + "child_pov_reduction = baseline_child_pov['poverty_rate'] - reform_child_pov['poverty_rate']\n", + "child_pov_pct_reduction = (child_pov_reduction / baseline_child_pov['poverty_rate'] * 100) if baseline_child_pov['poverty_rate'] > 0 else 0\n", + "\n", + "# Create results DataFrame (reform only)\n", + "results = [\n", + " {\n", + " \"Scenario\": \"Reform\",\n", + " \"Description\": \"Refundable EITC for children age 0-2\",\n", + " \"Net Cost\": format_currency(eitc_cost),\n", + " \"Overall Poverty Change (%)\": f\"{overall_pov_pct_reduction:.2f}%\",\n", + " \"Child Poverty Change (%)\": f\"{child_pov_pct_reduction:.2f}%\",\n", + " \"% Population Winning\": f\"{winners['pct_winners']:.2f}%\"\n", + " }\n", + "]\n", + "\n", + "df_results = pd.DataFrame(results)\n", + "\n", + "print(\"\\n\" + \"=\"*110)\n", + "print(\"UT EITC REFORM SUMMARY\")\n", + "print(\"=\"*110)\n", + "print(df_results.to_string(index=False))\n", + "print(\"=\"*110)\n", + "\n", + "# Export to CSV\n", + "df_results.to_csv(\"ut_eitc_reform_results.csv\", index=False)\n", + "print(\"\\nExported to: ut_eitc_reform_results.csv\")" + ] + } + ], + "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/states/ut/ut_eitc_reform_results.csv b/us/states/ut/ut_eitc_reform_results.csv new file mode 100644 index 0000000..3671953 --- /dev/null +++ b/us/states/ut/ut_eitc_reform_results.csv @@ -0,0 +1,2 @@ +Scenario,Description,Net Cost,Overall Poverty Change (%),Child Poverty Change (%),% Population Winning +Reform,Refundable EITC for children age 0-2,$14.22M,3.29%,7.84%,2.85% diff --git a/us/states/ut/ut_refundable_eitc_household_examples_v2.ipynb b/us/states/ut/ut_refundable_eitc_household_examples_v2.ipynb new file mode 100644 index 0000000..290598d --- /dev/null +++ b/us/states/ut/ut_refundable_eitc_household_examples_v2.ipynb @@ -0,0 +1,1140 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# UT Refundable EITC - Household Example Calculations\n", + "\n", + "This notebook verifies the UT refundable EITC reform is working correctly by examining individual household examples.\n", + "\n", + "## Reform Summary\n", + "- **Baseline**: Utah EITC = 20% of federal EITC (non-refundable, limited by tax liability)\n", + "- **Reform**: Makes the UT EITC fully refundable for households with a qualifying child age 2 or younger\n", + "\n", + "## Expected Behavior\n", + "1. Households with child age <= 2: Full UT EITC becomes refundable\n", + "2. Households with children only age 3+: UT EITC remains non-refundable\n", + "3. Childless households: UT EITC remains non-refundable" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "from policyengine_us import Microsimulation, Simulation\n", + "from policyengine_core.reforms import Reform\n", + "from policyengine_us.reforms.states.ut.ut_refundable_eitc import ut_refundable_eitc\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "def create_reform():\n", + " \"\"\"Reform: Make UT EITC refundable for households with children age 2 or younger\"\"\"\n", + " param_reform = Reform.from_dict(\n", + " {\n", + " \"gov.contrib.states.ut.eitc.in_effect\": {\n", + " \"2025-01-01.2100-12-31\": True\n", + " }\n", + " },\n", + " country_id=\"us\",\n", + " )\n", + " return (param_reform, ut_refundable_eitc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 1: Single Parent with 1-year-old (Should Benefit)\n", + "\n", + "Low-income single parent with an infant - should get full refundable EITC" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 1: Single Parent with 1-year-old, $20k income\n", + "======================================================================\n", + "\n", + "Federal EITC: $4,328.00\n", + "UT EITC (20% of federal): $865.60\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $900.00\n", + " UT non-refundable credits: $1,865.60\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $48,480.62\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: True\n", + " UT refundable EITC: $865.60\n", + " UT non-refundable EITC: $0.00\n", + " UT non-refundable credits: $1,000.00\n", + " UT refundable credits: $865.60\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $-865.60\n", + " Household net income: $49,346.22\n", + "\n", + ">>> BENEFIT FROM REFORM: $865.60\n" + ] + } + ], + "source": [ + "situation_1 = {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {2025: 28}, \"employment_income\": {2025: 20_000}},\n", + " \"child\": {\"age\": {2025: 1}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"child\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent\", \"child\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_1 = Simulation(situation=situation_1)\n", + "reform_1 = Simulation(situation=situation_1, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 1: Single Parent with 1-year-old, $20k income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_1.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_1.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_1.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_1.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_1.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_1.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_1.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_1.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_1.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_1.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_1.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_1.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_1.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_1.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_1.calculate('household_net_income', 2025)[0] - baseline_1.calculate('household_net_income', 2025)[0]:,.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 2: Single Parent with 5-year-old (Should NOT Benefit)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 2: Single Parent with 5-year-old, $20k income\n", + "======================================================================\n", + "\n", + "Federal EITC: $4,328.00\n", + "UT EITC (20% of federal): $865.60\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $900.00\n", + " UT non-refundable credits: $1,865.60\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $28,016.10\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: False\n", + " UT refundable EITC: $0.00\n", + " UT non-refundable EITC: $865.60\n", + " UT non-refundable credits: $1,865.60\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $28,016.10\n", + "\n", + ">>> BENEFIT FROM REFORM: $0.00\n" + ] + } + ], + "source": [ + "situation_2 = {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {2025: 30}, \"employment_income\": {2025: 20_000}},\n", + " \"child\": {\"age\": {2025: 5}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"child\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent\", \"child\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_2 = Simulation(situation=situation_2)\n", + "reform_2 = Simulation(situation=situation_2, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 2: Single Parent with 5-year-old, $20k income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_2.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_2.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_2.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_2.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_2.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_2.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_2.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_2.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_2.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_2.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_2.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_2.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_2.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_2.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_2.calculate('household_net_income', 2025)[0] - baseline_2.calculate('household_net_income', 2025)[0]:,.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 3: Married Couple with Infant (Should Benefit)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 3: Married Couple with Infant (age 0), $15k income\n", + "======================================================================\n", + "\n", + "Federal EITC: $4,328.00\n", + "UT EITC (20% of federal): $865.60\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $675.00\n", + " UT non-refundable credits: $1,965.60\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $49,530.96\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: True\n", + " UT refundable EITC: $865.60\n", + " UT non-refundable EITC: $0.00\n", + " UT non-refundable credits: $1,100.00\n", + " UT refundable credits: $865.60\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $-865.60\n", + " Household net income: $50,396.56\n", + "\n", + ">>> BENEFIT FROM REFORM: $865.60\n" + ] + } + ], + "source": [ + "situation_3 = {\n", + " \"people\": {\n", + " \"parent1\": {\"age\": {2025: 25}, \"employment_income\": {2025: 15_000}},\n", + " \"parent2\": {\"age\": {2025: 26}, \"employment_income\": {2025: 0}},\n", + " \"baby\": {\"age\": {2025: 0}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent1\", \"parent2\", \"baby\"]}},\n", + " \"families\": {\"family\": {\"members\": [\"parent1\", \"parent2\", \"baby\"]}},\n", + " \"marital_units\": {\"marital_unit\": {\"members\": [\"parent1\", \"parent2\"]}},\n", + " \"spm_units\": {\"spm_unit\": {\"members\": [\"parent1\", \"parent2\", \"baby\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent1\", \"parent2\", \"baby\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_3 = Simulation(situation=situation_3)\n", + "reform_3 = Simulation(situation=situation_3, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 3: Married Couple with Infant (age 0), $15k income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_3.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_3.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_3.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_3.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_3.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_3.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_3.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_3.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_3.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_3.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_3.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_3.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_3.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_3.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_3.calculate('household_net_income', 2025)[0] - baseline_3.calculate('household_net_income', 2025)[0]:,.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 4: Mixed Ages - One Qualifying, One Not (Should Benefit)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 4: Single Parent with kids age 1 and 7, $25k income\n", + "======================================================================\n", + "\n", + "Federal EITC: $6,804.51\n", + "UT EITC (20% of federal): $1,360.90\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $1,125.00\n", + " UT non-refundable credits: $2,360.90\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $59,971.83\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: True\n", + " UT refundable EITC: $1,360.90\n", + " UT non-refundable EITC: $0.00\n", + " UT non-refundable credits: $1,000.00\n", + " UT refundable credits: $1,360.90\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $-1,360.90\n", + " Household net income: $61,332.73\n", + "\n", + ">>> BENEFIT FROM REFORM: $1,360.91\n" + ] + } + ], + "source": [ + "situation_4 = {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {2025: 32}, \"employment_income\": {2025: 25_000}},\n", + " \"child1\": {\"age\": {2025: 1}, \"is_tax_unit_dependent\": {2025: True}},\n", + " \"child2\": {\"age\": {2025: 7}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"child1\", \"child2\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent\", \"child1\", \"child2\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_4 = Simulation(situation=situation_4)\n", + "reform_4 = Simulation(situation=situation_4, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 4: Single Parent with kids age 1 and 7, $25k income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_4.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_4.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_4.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_4.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_4.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_4.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_4.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_4.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_4.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_4.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_4.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_4.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_4.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_4.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_4.calculate('household_net_income', 2025)[0] - baseline_4.calculate('household_net_income', 2025)[0]:,.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 5: Child at Age Boundary (age 2 - Should Benefit)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 5: Single Parent with child age 2, $18k income\n", + "======================================================================\n", + "\n", + "Federal EITC: $4,328.00\n", + "UT EITC (20% of federal): $865.60\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $810.00\n", + " UT non-refundable credits: $1,865.60\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $47,112.42\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: True\n", + " UT refundable EITC: $865.60\n", + " UT non-refundable EITC: $0.00\n", + " UT non-refundable credits: $1,000.00\n", + " UT refundable credits: $865.60\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $-865.60\n", + " Household net income: $47,978.02\n", + "\n", + ">>> BENEFIT FROM REFORM: $865.60\n" + ] + } + ], + "source": [ + "situation_5 = {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {2025: 29}, \"employment_income\": {2025: 18_000}},\n", + " \"child\": {\"age\": {2025: 2}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"child\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent\", \"child\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_5 = Simulation(situation=situation_5)\n", + "reform_5 = Simulation(situation=situation_5, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 5: Single Parent with child age 2, $18k income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_5.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_5.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_5.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_5.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_5.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_5.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_5.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_5.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_5.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_5.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_5.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_5.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_5.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_5.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_5.calculate('household_net_income', 2025)[0] - baseline_5.calculate('household_net_income', 2025)[0]:,.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 6: Child Just Over Age Boundary (age 3 - Should NOT Benefit)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 6: Single Parent with child age 3, $18k income\n", + "======================================================================\n", + "\n", + "Federal EITC: $4,328.00\n", + "UT EITC (20% of federal): $865.60\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $810.00\n", + " UT non-refundable credits: $1,865.60\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $44,659.99\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: False\n", + " UT refundable EITC: $0.00\n", + " UT non-refundable EITC: $865.60\n", + " UT non-refundable credits: $1,865.60\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $44,659.99\n", + "\n", + ">>> BENEFIT FROM REFORM: $0.00\n" + ] + } + ], + "source": [ + "situation_6 = {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {2025: 29}, \"employment_income\": {2025: 18_000}},\n", + " \"child\": {\"age\": {2025: 3}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"child\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent\", \"child\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_6 = Simulation(situation=situation_6)\n", + "reform_6 = Simulation(situation=situation_6, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 6: Single Parent with child age 3, $18k income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_6.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_6.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_6.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_6.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_6.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_6.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_6.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_6.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_6.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_6.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_6.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_6.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_6.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_6.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_6.calculate('household_net_income', 2025)[0] - baseline_6.calculate('household_net_income', 2025)[0]:,.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 7: Childless Adult (Should NOT Benefit)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 7: Childless Adult, $12k income\n", + "======================================================================\n", + "\n", + "Federal EITC: $543.43\n", + "UT EITC (20% of federal): $108.69\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $540.00\n", + " UT non-refundable credits: $108.69\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $13,006.33\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: False\n", + " UT refundable EITC: $0.00\n", + " UT non-refundable EITC: $108.69\n", + " UT non-refundable credits: $108.69\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $13,006.33\n", + "\n", + ">>> BENEFIT FROM REFORM: $0.00\n" + ] + } + ], + "source": [ + "situation_7 = {\n", + " \"people\": {\n", + " \"adult\": {\"age\": {2025: 35}, \"employment_income\": {2025: 12_000}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"adult\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"adult\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_7 = Simulation(situation=situation_7)\n", + "reform_7 = Simulation(situation=situation_7, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 7: Childless Adult, $12k income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_7.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_7.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_7.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_7.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_7.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_7.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_7.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_7.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_7.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_7.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_7.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_7.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_7.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_7.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_7.calculate('household_net_income', 2025)[0] - baseline_7.calculate('household_net_income', 2025)[0]:,.2f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 8: Qualifying Child but NO Income (Should NOT Benefit)\n", + "\n", + "Even with a refundable EITC, households with no earned income should get $0 because the EITC phases in with income. This verifies we're only making the existing credit refundable, not creating a new credit." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 8: Single Parent with 1-year-old, $0 income\n", + "======================================================================\n", + "\n", + "Federal EITC: $0.00\n", + "UT EITC (20% of federal): $0.00\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $0.00\n", + " UT non-refundable credits: $1,000.00\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $28,042.52\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: True\n", + " UT refundable EITC: $0.00\n", + " UT non-refundable EITC: $0.00\n", + " UT non-refundable credits: $1,000.00\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $28,042.52\n", + "\n", + ">>> BENEFIT FROM REFORM: $0.00\n", + "\n", + "*** Key check: Federal EITC = $0 because EITC phases in with earned income ***\n", + "*** Therefore UT EITC = 20% * $0 = $0, and refundable EITC = $0 ***\n" + ] + } + ], + "source": [ + "situation_8 = {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {2025: 28}, \"employment_income\": {2025: 0}},\n", + " \"child\": {\"age\": {2025: 1}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"child\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent\", \"child\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_8 = Simulation(situation=situation_8)\n", + "reform_8 = Simulation(situation=situation_8, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 8: Single Parent with 1-year-old, $0 income\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_8.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_8.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_8.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_8.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_8.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_8.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_8.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_8.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_8.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_8.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_8.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_8.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_8.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_8.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_8.calculate('household_net_income', 2025)[0] - baseline_8.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n*** Key check: Federal EITC = $0 because EITC phases in with earned income ***\")\n", + "print(f\"*** Therefore UT EITC = 20% * $0 = $0, and refundable EITC = $0 ***\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 9: Qualifying Child with $5k Income (Should Benefit - Partial EITC)\n", + "\n", + "With $5k income, the EITC is in the phase-in range. This household should benefit since they get a partial federal EITC that becomes refundable." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "======================================================================\n", + "EXAMPLE 9: Single Parent with 1-year-old, $5k income (phase-in)\n", + "======================================================================\n", + "\n", + "Federal EITC: $1,700.00\n", + "UT EITC (20% of federal): $340.00\n", + "\n", + "Baseline (non-refundable):\n", + " UT income tax before credits: $225.00\n", + " UT non-refundable credits: $1,340.00\n", + " UT refundable credits: $0.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $0.00\n", + " Household net income: $34,275.12\n", + "\n", + "Reform (refundable for age <= 2):\n", + " Has qualifying child: True\n", + " UT refundable EITC: $340.00\n", + " UT non-refundable EITC: $0.00\n", + " UT non-refundable credits: $1,000.00\n", + " UT refundable credits: $340.00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Invalid values for enum StateGroup: ['UT']. These will be encoded as index 0.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " UT income tax: $-340.00\n", + " Household net income: $34,615.12\n", + "\n", + ">>> BENEFIT FROM REFORM: $340.00\n", + "\n", + "*** At $5k income, federal EITC is in phase-in range ***\n", + "*** UT EITC = 20% of federal, and this becomes refundable ***\n" + ] + } + ], + "source": [ + "situation_9 = {\n", + " \"people\": {\n", + " \"parent\": {\"age\": {2025: 28}, \"employment_income\": {2025: 5_000}},\n", + " \"child\": {\"age\": {2025: 1}, \"is_tax_unit_dependent\": {2025: True}},\n", + " },\n", + " \"tax_units\": {\"tax_unit\": {\"members\": [\"parent\", \"child\"]}},\n", + " \"households\": {\"household\": {\"members\": [\"parent\", \"child\"], \"state_code\": {2025: \"UT\"}}},\n", + "}\n", + "\n", + "baseline_9 = Simulation(situation=situation_9)\n", + "reform_9 = Simulation(situation=situation_9, reform=create_reform())\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EXAMPLE 9: Single Parent with 1-year-old, $5k income (phase-in)\")\n", + "print(\"=\"*70)\n", + "print(f\"\\nFederal EITC: ${baseline_9.calculate('eitc', 2025)[0]:,.2f}\")\n", + "print(f\"UT EITC (20% of federal): ${baseline_9.calculate('ut_eitc', 2025)[0]:,.2f}\")\n", + "print(f\"\\nBaseline (non-refundable):\")\n", + "print(f\" UT income tax before credits: ${baseline_9.calculate('ut_income_tax_before_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${baseline_9.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${baseline_9.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${baseline_9.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${baseline_9.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\nReform (refundable for age <= 2):\")\n", + "print(f\" Has qualifying child: {reform_9.calculate('ut_has_qualifying_child_for_refundable_eitc', 2025)[0]}\")\n", + "print(f\" UT refundable EITC: ${reform_9.calculate('ut_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable EITC: ${reform_9.calculate('ut_non_refundable_eitc', 2025)[0]:,.2f}\")\n", + "print(f\" UT non-refundable credits: ${reform_9.calculate('ut_non_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT refundable credits: ${reform_9.calculate('ut_refundable_credits', 2025)[0]:,.2f}\")\n", + "print(f\" UT income tax: ${reform_9.calculate('ut_income_tax', 2025)[0]:,.2f}\")\n", + "print(f\" Household net income: ${reform_9.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n>>> BENEFIT FROM REFORM: ${reform_9.calculate('household_net_income', 2025)[0] - baseline_9.calculate('household_net_income', 2025)[0]:,.2f}\")\n", + "print(f\"\\n*** At $5k income, federal EITC is in phase-in range ***\")\n", + "print(f\"*** UT EITC = 20% of federal, and this becomes refundable ***\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Summary Table" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==========================================================================================\n", + "SUMMARY: UT Refundable EITC Household Examples\n", + "==========================================================================================\n", + " Example Fed EITC UT EITC Refundable Benefit Status\n", + " 1: Child age 1, $20k $4,328 $866 $866 $865.60 PASS\n", + " 2: Child age 5, $20k $4,328 $866 $0 $0.00 PASS\n", + " 3: Infant age 0, $15k $4,328 $866 $866 $865.60 PASS\n", + "4: Kids age 1 & 7, $25k $6,805 $1,361 $1,361 $1,360.91 PASS\n", + " 5: Child age 2, $18k $4,328 $866 $866 $865.60 PASS\n", + " 6: Child age 3, $18k $4,328 $866 $0 $0.00 PASS\n", + " 7: Childless, $12k $543 $109 $0 $0.00 PASS\n", + " 8: Child age 1, $0 $0 $0 $0 $0.00 PASS\n", + " 9: Child age 1, $5k $1,700 $340 $340 $340.00 PASS\n", + "==========================================================================================\n", + "\n", + "All tests passed: True\n", + "\n", + "----------------------------------------------------------------------\n", + "KEY INSIGHT - EITC Phase-in Verification:\n", + "----------------------------------------------------------------------\n", + "Example 8 ($0 income): Fed EITC = $0, Benefit = $0\n", + "Example 9 ($5k income): Fed EITC phases in, Benefit > $0\n", + "\n", + "This confirms the reform only makes the EXISTING credit refundable.\n", + "The EITC phase-in structure is preserved.\n", + "----------------------------------------------------------------------\n" + ] + } + ], + "source": [ + "examples = [\n", + " (\"1: Child age 1, $20k\", baseline_1, reform_1, True),\n", + " (\"2: Child age 5, $20k\", baseline_2, reform_2, False),\n", + " (\"3: Infant age 0, $15k\", baseline_3, reform_3, True),\n", + " (\"4: Kids age 1 & 7, $25k\", baseline_4, reform_4, True),\n", + " (\"5: Child age 2, $18k\", baseline_5, reform_5, True),\n", + " (\"6: Child age 3, $18k\", baseline_6, reform_6, False),\n", + " (\"7: Childless, $12k\", baseline_7, reform_7, False),\n", + " (\"8: Child age 1, $0\", baseline_8, reform_8, False),\n", + " (\"9: Child age 1, $5k\", baseline_9, reform_9, True),\n", + "]\n", + "\n", + "summary_data = []\n", + "for desc, baseline, reform, expected_benefit in examples:\n", + " baseline_income = baseline.calculate('household_net_income', 2025)[0]\n", + " reform_income = reform.calculate('household_net_income', 2025)[0]\n", + " benefit = reform_income - baseline_income\n", + " federal_eitc = baseline.calculate('eitc', 2025)[0]\n", + " ut_eitc = baseline.calculate('ut_eitc', 2025)[0]\n", + " refundable_eitc = reform.calculate('ut_refundable_eitc', 2025)[0]\n", + " actual_benefit = benefit > 0.5\n", + " status = \"PASS\" if actual_benefit == expected_benefit else \"FAIL\"\n", + " \n", + " summary_data.append({\n", + " \"Example\": desc,\n", + " \"Fed EITC\": f\"${federal_eitc:,.0f}\",\n", + " \"UT EITC\": f\"${ut_eitc:,.0f}\",\n", + " \"Refundable\": f\"${refundable_eitc:,.0f}\",\n", + " \"Benefit\": f\"${benefit:,.2f}\",\n", + " \"Status\": status,\n", + " })\n", + "\n", + "df_summary = pd.DataFrame(summary_data)\n", + "print(\"=\"*90)\n", + "print(\"SUMMARY: UT Refundable EITC Household Examples\")\n", + "print(\"=\"*90)\n", + "print(df_summary.to_string(index=False))\n", + "print(\"=\"*90)\n", + "\n", + "all_pass = all(row[\"Status\"] == \"PASS\" for row in summary_data)\n", + "print(f\"\\nAll tests passed: {all_pass}\")\n", + "\n", + "print(\"\\n\" + \"-\"*70)\n", + "print(\"KEY INSIGHT - EITC Phase-in Verification:\")\n", + "print(\"-\"*70)\n", + "print(\"Example 8 ($0 income): Fed EITC = $0, Benefit = $0\")\n", + "print(\"Example 9 ($5k income): Fed EITC phases in, Benefit > $0\")\n", + "print(\"\\nThis confirms the reform only makes the EXISTING credit refundable.\")\n", + "print(\"The EITC phase-in structure is preserved.\")\n", + "print(\"-\"*70)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Summary table exported to: ut_refundable_eitc_summary.csv\n" + ] + } + ], + "source": [ + "# Export summary table to CSV\n", + "df_summary.to_csv(\"ut_refundable_eitc_summary.csv\", index=False)\n", + "print(f\"Summary table exported to: ut_refundable_eitc_summary.csv\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/us/states/ut/ut_refundable_eitc_summary.csv b/us/states/ut/ut_refundable_eitc_summary.csv new file mode 100644 index 0000000..1b9dcb2 --- /dev/null +++ b/us/states/ut/ut_refundable_eitc_summary.csv @@ -0,0 +1,10 @@ +Example,Fed EITC,UT EITC,Refundable,Benefit,Status +"1: Child age 1, $20k","$4,328",$866,$866,$865.60,PASS +"2: Child age 5, $20k","$4,328",$866,$0,$0.00,PASS +"3: Infant age 0, $15k","$4,328",$866,$866,$865.60,PASS +"4: Kids age 1 & 7, $25k","$6,805","$1,361","$1,361","$1,360.91",PASS +"5: Child age 2, $18k","$4,328",$866,$866,$865.60,PASS +"6: Child age 3, $18k","$4,328",$866,$0,$0.00,PASS +"7: Childless, $12k",$543,$109,$0,$0.00,PASS +"8: Child age 1, $0",$0,$0,$0,$0.00,PASS +"9: Child age 1, $5k","$1,700",$340,$340,$340.00,PASS