Skip to content

Commit e0d0972

Browse files
authored
Merge pull request PSLmodels#1084 from jdebacker/nonfilers
Merging
2 parents dd21944 + 44755b6 commit e0d0972

15 files changed

Lines changed: 233 additions & 17 deletions

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.15.3] - 2025-01-24 12:00:00
9+
10+
### Added
11+
12+
- Two new parameters, `income_tax_filer` and `wealth_tax_filer`, that determine whether certain types `j` pay income or wealth taxes, respectively. See PR [#1084](https://github.com/PSLmodels/OG-Core/pull/1084)
13+
814
## [0.15.2] - 2025-01-22 12:00:00
915

1016
### Added
1117

12-
- A new parameters, `r_gov_DY` and `r_gov_DY2`, that allow the government interest rate to be a function of the debt-to-GDP ratio. See PR [#1037](https://github.com/PSLmodels/OG-Core/pull/1037)
18+
- Two new parameters, `r_gov_DY` and `r_gov_DY2`, that allow the government interest rate to be a function of the debt-to-GDP ratio. See PR [#1037](https://github.com/PSLmodels/OG-Core/pull/1037)
1319

1420
## [0.15.1] - 2026-01-19 12:00:00
1521

@@ -499,6 +505,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
499505
- Any earlier versions of OG-USA can be found in the [`OG-Core`](https://github.com/PSLmodels/OG-Core) repository [release history](https://github.com/PSLmodels/OG-Core/releases) from [v.0.6.4](https://github.com/PSLmodels/OG-Core/releases/tag/v0.6.4) (Jul. 20, 2021) or earlier.
500506

501507

508+
[0.15.3]: https://github.com/PSLmodels/OG-Core/compare/v0.15.2...v0.15.3
502509
[0.15.2]: https://github.com/PSLmodels/OG-Core/compare/v0.15.1...v0.15.2
503510
[0.15.1]: https://github.com/PSLmodels/OG-Core/compare/v0.15.0...v0.15.1
504511
[0.15.0]: https://github.com/PSLmodels/OG-Core/compare/v0.14.14...v0.15.0

ogcore/SS.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,10 @@ def SS_solver(
914914
np.reshape(p.labor_income_tax_noncompliance_rate[-1, :], (1, p.J)),
915915
(p.S, 1),
916916
)
917+
income_tax_filer_2D = np.tile(
918+
np.reshape(p.income_tax_filer[-1, :], (1, p.J)),
919+
(p.S, 1),
920+
)
917921
mtry_ss = tax.MTR_income(
918922
r_p_ss,
919923
wss,
@@ -925,6 +929,7 @@ def SS_solver(
925929
etr_params_3D,
926930
mtry_params_3D,
927931
capital_noncompliance_rate_2D,
932+
income_tax_filer_2D,
928933
p,
929934
)
930935
mtrx_ss = tax.MTR_income(
@@ -938,6 +943,7 @@ def SS_solver(
938943
etr_params_3D,
939944
mtrx_params_3D,
940945
labor_noncompliance_rate_2D,
946+
income_tax_filer_2D,
941947
p,
942948
)
943949
etr_ss = tax.ETR_income(
@@ -950,6 +956,7 @@ def SS_solver(
950956
etr_params_3D,
951957
labor_noncompliance_rate_2D,
952958
capital_noncompliance_rate_2D,
959+
income_tax_filer_2D,
953960
p,
954961
)
955962

ogcore/TPI.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import os
2323
import warnings
2424
import logging
25+
from distributed import wait
2526

2627
if not SHOW_RUNTIME:
2728
warnings.simplefilter("ignore", RuntimeWarning)
@@ -819,8 +820,6 @@ def run_TPI(p, client=None):
819820
futures.append(f)
820821
try:
821822
# Wait for futures with timeout, then gather results
822-
from distributed import wait
823-
824823
done, not_done = wait(futures, timeout=600)
825824
if not_done:
826825
# Some futures didn't complete in time
@@ -1315,6 +1314,10 @@ def run_TPI(p, client=None):
13151314
),
13161315
(1, p.S, 1),
13171316
)
1317+
income_tax_filer_3D = np.tile(
1318+
np.reshape(p.income_tax_filer[: p.T, :], (p.T, 1, p.J)),
1319+
(1, p.S, 1),
1320+
)
13181321
e_3D = p.e
13191322
mtry_path = tax.MTR_income(
13201323
r_p_path[: p.T],
@@ -1327,6 +1330,7 @@ def run_TPI(p, client=None):
13271330
etr_params_4D,
13281331
mtry_params_4D,
13291332
capital_noncompliance_rate_3D,
1333+
income_tax_filer_3D,
13301334
p,
13311335
)
13321336
mtrx_path = tax.MTR_income(
@@ -1340,6 +1344,7 @@ def run_TPI(p, client=None):
13401344
etr_params_4D,
13411345
mtrx_params_4D,
13421346
labor_noncompliance_rate_3D,
1347+
income_tax_filer_3D,
13431348
p,
13441349
)
13451350
etr_path = tax.ETR_income(
@@ -1352,9 +1357,9 @@ def run_TPI(p, client=None):
13521357
etr_params_4D,
13531358
labor_noncompliance_rate_3D,
13541359
capital_noncompliance_rate_3D,
1360+
income_tax_filer_3D,
13551361
p,
13561362
)
1357-
13581363
# Note that implicitly in this computation is that immigrants'
13591364
# wealth is all in the form of private capital
13601365
I_d = aggr.get_I(

ogcore/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
from ogcore.txfunc import *
2121
from ogcore.utils import *
2222

23-
__version__ = "0.15.2"
23+
__version__ = "0.15.3"

ogcore/default_parameters.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4304,6 +4304,62 @@
43044304
}
43054305
}
43064306
},
4307+
"income_tax_filer": {
4308+
"title": "Income tax filer indicator",
4309+
"description": "Binary indicator for whether lifetime income type j is subject to income taxes. Non-filers (tax_filer[j]=0) are not subject to income taxes but still pay payroll taxes.",
4310+
"section_1": "Fiscal Policy Parameters",
4311+
"section_2": "Taxes",
4312+
"notes": "Specified by time T and lifetime income group J. Defaults to 1.0 (all groups file). Can be set to values between 0 and 1 to represent the share of group j that files.",
4313+
"type": "float",
4314+
"number_dims": 2,
4315+
"value": [
4316+
{
4317+
"value": [[
4318+
1.0,
4319+
1.0,
4320+
1.0,
4321+
1.0,
4322+
1.0,
4323+
1.0,
4324+
1.0
4325+
]]
4326+
}
4327+
],
4328+
"validators": {
4329+
"range": {
4330+
"min": 0.0,
4331+
"max": 1.0
4332+
}
4333+
}
4334+
},
4335+
"wealth_tax_filer": {
4336+
"title": "Wealth tax filer indicator",
4337+
"description": "Binary indicator for whether lifetime income type j is subject to wealth taxes. Non-filers (wealth_tax_filer[j]=0) are not subject to wealth taxes but still pay payroll taxes.",
4338+
"section_1": "Fiscal Policy Parameters",
4339+
"section_2": "Taxes",
4340+
"notes": "Specified by time T and lifetime income group J. Defaults to 1.0 (all groups file). Can be set to values between 0 and 1 to represent the share of group j that files.",
4341+
"type": "float",
4342+
"number_dims": 2,
4343+
"value": [
4344+
{
4345+
"value": [[
4346+
1.0,
4347+
1.0,
4348+
1.0,
4349+
1.0,
4350+
1.0,
4351+
1.0,
4352+
1.0
4353+
]]
4354+
}
4355+
],
4356+
"validators": {
4357+
"range": {
4358+
"min": 0.0,
4359+
"max": 1.0
4360+
}
4361+
}
4362+
},
43074363
"nu": {
43084364
"title": "Parameter for convergence rate of functional iteration",
43094365
"description": "Parameter for convergence rate of functional iteration.",

ogcore/household.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,15 +480,21 @@ def FOC_savings(
480480
beta = p.beta[j]
481481
if method == "SS":
482482
tax_noncompliance = p.capital_income_tax_noncompliance_rate[-1, j]
483+
income_tax_filer = p.income_tax_filer[-1, j]
484+
wealth_tax_filer = p.wealth_tax_filer[-1, j]
483485
e = np.squeeze(p.e[-1, :, j])
484486
elif method == "TPI_scalar":
485487
tax_noncompliance = p.capital_income_tax_noncompliance_rate[0, j]
488+
income_tax_filer = p.income_tax_filer[0, j]
489+
wealth_tax_filer = p.wealth_tax_filer[0, j]
486490
e = np.squeeze(p.e[0, :, j])
487491
else:
488492
length = r.shape[0]
489493
tax_noncompliance = p.capital_income_tax_noncompliance_rate[
490494
t : t + length, j
491495
]
496+
income_tax_filer = p.income_tax_filer[t : t + length, j]
497+
wealth_tax_filer = p.wealth_tax_filer[t : t + length, j]
492498
e_long = np.concatenate(
493499
(
494500
p.e,
@@ -502,15 +508,21 @@ def FOC_savings(
502508
beta = p.beta
503509
if method == "SS":
504510
tax_noncompliance = p.capital_income_tax_noncompliance_rate[-1, :]
511+
income_tax_filer = p.income_tax_filer[-1, :]
512+
wealth_tax_filer = p.wealth_tax_filer[-1, :]
505513
e = np.squeeze(p.e[-1, :, :])
506514
elif method == "TPI_scalar":
507515
tax_noncompliance = p.capital_income_tax_noncompliance_rate[0, :]
516+
income_tax_filer = p.income_tax_filer[0, :]
517+
wealth_tax_filer = p.wealth_tax_filer[0, :]
508518
e = np.squeeze(p.e[0, :, :])
509519
else:
510520
length = r.shape[0]
511521
tax_noncompliance = p.capital_income_tax_noncompliance_rate[
512522
t : t + length, :
513523
]
524+
income_tax_filer = p.income_tax_filer[t : t + length, :]
525+
wealth_tax_filer = p.wealth_tax_filer[t : t + length, :]
514526
e_long = np.concatenate(
515527
(
516528
p.e,
@@ -572,10 +584,11 @@ def FOC_savings(
572584
etr_params,
573585
mtry_params,
574586
tax_noncompliance,
587+
income_tax_filer,
575588
p,
576589
)
577590
)
578-
- tax.MTR_wealth(b, h_wealth, m_wealth, p_wealth)
591+
- tax.MTR_wealth(b, h_wealth, m_wealth, p_wealth, wealth_tax_filer)
579592
)
580593
savings_ut = (
581594
rho * np.exp(-p.sigma * p.g_y) * chi_b * b_splus1 ** (-p.sigma)
@@ -685,14 +698,17 @@ def FOC_labor(
685698
if j is not None:
686699
if method == "SS":
687700
tax_noncompliance = p.labor_income_tax_noncompliance_rate[-1, j]
701+
income_tax_filer = p.income_tax_filer[-1, j]
688702
e = np.squeeze(p.e[-1, :, j])
689703
elif method == "TPI_scalar":
690704
tax_noncompliance = p.labor_income_tax_noncompliance_rate[0, j]
705+
income_tax_filer = p.income_tax_filer[0, j]
691706
e = np.squeeze(p.e[0, -1, j])
692707
else:
693708
tax_noncompliance = p.labor_income_tax_noncompliance_rate[
694709
t : t + length, j
695710
]
711+
income_tax_filer = p.income_tax_filer[t : t + length, j]
696712
e_long = np.concatenate(
697713
(
698714
p.e,
@@ -704,14 +720,17 @@ def FOC_labor(
704720
else:
705721
if method == "SS":
706722
tax_noncompliance = p.labor_income_tax_noncompliance_rate[-1, :]
723+
income_tax_filer = p.income_tax_filer[-1, :]
707724
e = np.squeeze(p.e[-1, :, :])
708725
elif method == "TPI_scalar":
709726
tax_noncompliance = p.labor_income_tax_noncompliance_rate[0, :]
727+
income_tax_filer = p.income_tax_filer[0, :]
710728
e = np.squeeze(p.e[0, -1, :])
711729
else:
712730
tax_noncompliance = p.labor_income_tax_noncompliance_rate[
713731
t : t + length, :
714732
]
733+
income_tax_filer = p.income_tax_filer[t : t + length, :]
715734
e_long = np.concatenate(
716735
(
717736
p.e,
@@ -761,6 +780,7 @@ def FOC_labor(
761780
etr_params,
762781
mtrx_params,
763782
tax_noncompliance,
783+
income_tax_filer,
764784
p,
765785
)
766786
)

ogcore/parameters.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ def compute_default_params(self):
208208
"labor_income_tax_noncompliance_rate",
209209
"capital_income_tax_noncompliance_rate",
210210
"replacement_rate_adjust",
211+
"income_tax_filer",
212+
"wealth_tax_filer",
211213
]
212214
for item in tp_param_list3:
213215
param_in = getattr(self, item)

0 commit comments

Comments
 (0)