Add tax_filer parameter to model income tax non-filers
#1084
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements a new tax_filer parameter that enables modeling of income tax non-filers in OG-Core. This feature allows researchers to analyze filing thresholds, tax compliance policies, and the economic effects of requiring low-income households to file taxes.
Motivation
In reality, many low-income households are not required to file income tax returns due to filing thresholds (e.g., standard deduction). This PR provides the capability to model this important feature of the tax system.
Implementation Approach
After evaluating two approaches:
We selected Approach 2 because it avoids numerical kinks within j-group optimization and aligns with existing J-differentiated parameters.
Changes
Core Implementation (3 files)
ogcore/default_parameters.json(lines 4251-4278)tax_filerparameter: J-length vector of floats (0.0 to 1.0)[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0](all groups file)tax_filer[j]= 0.0 → non-filer (no income tax, zero MTRs)tax_filer[j]= 1.0 → full filer (normal tax treatment)tax_filer[j]= 0.5 → partial filer (50% of group files)ogcore/tax.pyincome_tax_liab()(lines 378-396): Scales income tax bytax_filer[j], payroll tax unaffectedMTR_income()(lines 113-190): Added optionaljparameter, scales MTR bytax_filer[j]ogcore/household.pyFOC_labor()(line 718): PassjtoMTR_income()FOC_savings()(line 529): PassjtoMTR_income()Documentation (3 files)
examples/run_ogcore_nonfiler_example.pyj=0non-filers) vs reform (all filers)examples/TAX_FILER_README.mdTAX_FILER_IMPLEMENTATION_SUMMARY.mdKey Features
✅ Economically consistent: Both ATR and MTR are zero for non-filers
✅ Numerically robust: No kinks within j-group optimization
✅ Backward compatible: Default behavior unchanged (all groups file)
✅ Well-tested: All 85 existing tests pass with no regressions
✅ Validated: Full model runs confirm correct behavior
✅ Documented: Examples and README provided
Testing
Existing Tests
tests/test_tax.py)tests/test_household.py)Model Run Validation
Baseline:
tax_filer = [0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0](j=0non-filers)Reform:
tax_filer = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0](all filers)Results when
j=0transitions from non-filer to filer:These results confirm the implementation is working correctly.
Usage Example
See
examples/run_ogcore_nonfiler_example.pyfor a complete example.Economic Interpretation
Non-filers (
tax_filer[j] = 0.0):Policy Applications:
Backward Compatibility
✅ Fully backward compatible
tax_filer = [1.0, 1.0, ...]preserves original behaviorMTR_income()defaults to NoneChecklist
🤖 Generated with https://claude.com/claude-code
Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com