Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions tests/expected_taxcalc_results_2022.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Expected 2022 EITC and ACTC aggregates from IRS Statistics of Income
# Publication 1304 (2022), Table A.
#
# DATA SOURCE
# Internal Revenue Service, "Statistics of Income — 2022 Individual
# Income Tax Returns," Publication 1304, Table A — "Selected Income
# and Tax Items, by Size and Accumulated Size of Adjusted Gross Income"
#
# DEFINITIONS
# n_returns_mil : Number of returns with a positive credit amount (millions).
# amount_bil : Total credit amount (billions of dollars).
#
# NOTES
# EITC = Earned Income Credit (refundable); taxcalc variable "eitc".
# ACTC = Additional Child Tax Credit (refundable); taxcalc variable "c11070".

eitc:
n_returns_mil: 24.09
amount_bil: 60.07

actc:
n_returns_mil: 18.08
amount_bil: 34.84
95 changes: 95 additions & 0 deletions tests/test_taxcalc_results_2022.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""
Test that 2022 Tax-Calculator results for EITC and ACTC match
IRS Statistics of Income (SOI) Publication 1304 aggregates.

Comparisons (all tax units, year 2022):
- Earned Income Credit (EITC): count (millions) and amount (billions)
- Additional Child Tax Credit (ACTC): count (millions) and amount (billions)
"""

import yaml
import pytest
import taxcalc

from tmd.imputation_assumptions import TAXYEAR, SOI_IITAX_SPEC, CREDIT_CLAIMING

OLD_CREDIT_CLAIMING = False
CLAIM_PROB_SCALE = {
"eitc": 1.04,
"actc": 1.57,
}
NEW_CREDIT_CLAIMING = {
"eitc_claim_prob_scale": {"2022": CLAIM_PROB_SCALE["eitc"]},
"actc_claim_prob_scale": {"2022": CLAIM_PROB_SCALE["actc"]},
}
MAX_RELATIVE_TOLERANCE = {
"n_returns_mil": 0.07,
"amount_bil": 0.002,
}


@pytest.mark.skipif(
TAXYEAR != 2022,
reason="expected values are calibrated to TAXYEAR=2022",
)
def test_taxcalc_results_2022(
tests_folder, tmd_variables, tmd_weights_path, tmd_growfactors_path
):
epath = tests_folder / "expected_taxcalc_results_2022.yaml"
with open(epath, "r", encoding="utf-8") as f:
expect = yaml.safe_load(f)

pol = taxcalc.Policy()
pol.implement_reform(SOI_IITAX_SPEC)
if OLD_CREDIT_CLAIMING:
pol.implement_reform(CREDIT_CLAIMING)
else:
pol.implement_reform(NEW_CREDIT_CLAIMING)
recs = taxcalc.Records(
data=tmd_variables,
start_year=TAXYEAR,
weights=str(tmd_weights_path),
gfactors=taxcalc.GrowFactors(
growfactors_filename=str(tmd_growfactors_path)
),
adjust_ratios=None,
exact_calculations=True,
weights_scale=1.0,
)
sim = taxcalc.Calculator(policy=pol, records=recs)
sim.advance_to_year(TAXYEAR)
sim.calc_all()

wt = sim.array("s006")
eitc = sim.array("eitc")
actc = sim.array("c11070")

actual = {
"eitc": {
"n_returns_mil": float((wt * (eitc > 0)).sum() * 1e-6),
"amount_bil": float((wt * eitc).sum() * 1e-9),
},
"actc": {
"n_returns_mil": float((wt * (actc > 0)).sum() * 1e-6),
"amount_bil": float((wt * actc).sum() * 1e-9),
},
}

errors = []
for credit in ("eitc", "actc"):
for metric in ("n_returns_mil", "amount_bil"):
act = actual[credit][metric]
exp = expect[credit][metric]
rel_diff = act / exp - 1.0
if abs(rel_diff) >= MAX_RELATIVE_TOLERANCE[metric]:
errors.append(
f"{credit}.{metric}: "
f"act={act:.2f} exp={exp:.2f} "
f"rel_diff={rel_diff:+.4f} "
f"tol={MAX_RELATIVE_TOLERANCE[metric]:.4f}"
)

if errors:
raise ValueError(
"\nACT-vs-EXP TAXCALC 2022 DIFFERENCES:\n" + "\n".join(errors)
)
Loading