Add get_payroll_tax_revenue function for correct payroll tax revenue - #1184
Add get_payroll_tax_revenue function for correct payroll tax revenue#1184arihantlodha-cmd wants to merge 3 commits into
get_payroll_tax_revenue function for correct payroll tax revenue#1184Conversation
Closes PSLmodels#1023. Previously payroll tax revenue was always computed as frac_tax_payroll * iit_payroll_tax_revenue, which is incorrect when a user models payroll taxes explicitly via tau_payroll (and excludes them from the tax functions). Adds get_payroll_tax_revenue, which uses tau_payroll * w * L when tau_payroll is nonzero and falls back to the existing fraction-of- combined-revenue calculation otherwise. Identical results when tau_payroll is zero (the default), so default runs are unchanged. Adds test_get_payroll_tax_revenue covering both branches for SS and TPI.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1184 +/- ##
=========================================
Coverage ? 72.70%
=========================================
Files ? 22
Lines ? 5734
Branches ? 0
=========================================
Hits ? 4169
Misses ? 1565
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
@arihantlodha-cmd Thanks for this PR. Regarding your question, yes, let's fix the calculation of payroll_tax_revenue = get_payroll_tax_revenue(
w, L, iit_payroll_tax_revenue, p, method
)
if np.any(p.tau_payroll != 0):
iit_payroll_tax_revenue += payroll_tax_revenue
iit_revenue = iit_payroll_tax_revenue - payroll_tax_revenue |
|
Also, please run |
Per review feedback (PSLmodels#1184): when payroll taxes are modeled explicitly via tau_payroll (and excluded from the income+payroll tax functions), iit_payroll_tax_revenue holds only income tax, so payroll_tax_revenue is now added back into it before computing total_tax_revenue and iit_revenue. Regenerated the test_revenue golden values, whose params use tau_payroll=0.5: each new total equals the previous total plus payroll_tax_revenue (verified by construction). No change to default (tau_payroll == 0) runs.
|
Thanks for the review! Addressed both points:
Ran |
Closes #1023.
Adds a dedicated
get_payroll_tax_revenuefunction inaggregates.pyand calls it fromrevenue()in place of the two inline calculations.Previously payroll tax revenue was always computed as
frac_tax_payroll * iit_payroll_tax_revenue, which assumes payroll taxes are embedded in the estimated income and payroll tax functions and separated out via thefrac_tax_payrollseries. As noted in the issue, that is incorrect when a user instead models payroll taxes explicitly throughtau_payroll(and excludes them frometr_params/mtrx_params/mtry_params). The new function branches ontau_payroll:np.any(tau_payroll != 0):payroll_tax_revenue = tau_payroll * w * L(aggregate labor summed across industries)tau_payroll == 0): the existingfrac_tax_payroll * iit_payroll_tax_revenueThe two are identical when
tau_payroll == 0, so default runs are unchanged (existingtest_revenuestill passes).A few implementation choices, flagged for review:
get_payroll_tax_revenuerather thanpayroll_tax_revenueto match the module'sget_*convention and to avoid shadowing the localpayroll_tax_revenuevariable insiderevenue(). Happy to rename if you'd prefer.Larrives per-industry inrevenue(), so aggregate labor income usesL.sum(-1).Testing
test_get_payroll_tax_revenuecovering both branches for SS and TPI.pytest tests/test_aggregates.py -m "not local and not benchmark"→ 43 passed;ruff format --check .andruff check .clean.One question for maintainers: when payroll taxes are modeled via
tau_payrolland excluded from the tax functions,iit_payroll_tax_revenueno longer contains payroll revenue, soiit_revenue = iit_payroll_tax_revenue - payroll_tax_revenue(and payroll's contribution tototal_tax_revenue) may also need revisiting. I left those as-is to keep this PR scoped to the issue — glad to follow up if you'd like that handled here too.