Skip to content
Merged
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
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.15.3] - 2025-01-24 12:00:00

### Added

- 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)

## [0.15.2] - 2025-01-22 12:00:00

### Added

- 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)
- 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)

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

Expand Down Expand Up @@ -499,6 +505,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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.


[0.15.3]: https://github.com/PSLmodels/OG-Core/compare/v0.15.2...v0.15.3
[0.15.2]: https://github.com/PSLmodels/OG-Core/compare/v0.15.1...v0.15.2
[0.15.1]: https://github.com/PSLmodels/OG-Core/compare/v0.15.0...v0.15.1
[0.15.0]: https://github.com/PSLmodels/OG-Core/compare/v0.14.14...v0.15.0
Expand Down
7 changes: 7 additions & 0 deletions ogcore/SS.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,10 @@ def SS_solver(
np.reshape(p.labor_income_tax_noncompliance_rate[-1, :], (1, p.J)),
(p.S, 1),
)
income_tax_filer_2D = np.tile(
np.reshape(p.income_tax_filer[-1, :], (1, p.J)),
(p.S, 1),
)
mtry_ss = tax.MTR_income(
r_p_ss,
wss,
Expand All @@ -925,6 +929,7 @@ def SS_solver(
etr_params_3D,
mtry_params_3D,
capital_noncompliance_rate_2D,
income_tax_filer_2D,
p,
)
mtrx_ss = tax.MTR_income(
Expand All @@ -938,6 +943,7 @@ def SS_solver(
etr_params_3D,
mtrx_params_3D,
labor_noncompliance_rate_2D,
income_tax_filer_2D,
p,
)
etr_ss = tax.ETR_income(
Expand All @@ -950,6 +956,7 @@ def SS_solver(
etr_params_3D,
labor_noncompliance_rate_2D,
capital_noncompliance_rate_2D,
income_tax_filer_2D,
p,
)

Expand Down
11 changes: 8 additions & 3 deletions ogcore/TPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import os
import warnings
import logging
from distributed import wait

if not SHOW_RUNTIME:
warnings.simplefilter("ignore", RuntimeWarning)
Expand Down Expand Up @@ -819,8 +820,6 @@ def run_TPI(p, client=None):
futures.append(f)
try:
# Wait for futures with timeout, then gather results
from distributed import wait

done, not_done = wait(futures, timeout=600)
if not_done:
# Some futures didn't complete in time
Expand Down Expand Up @@ -1315,6 +1314,10 @@ def run_TPI(p, client=None):
),
(1, p.S, 1),
)
income_tax_filer_3D = np.tile(
np.reshape(p.income_tax_filer[: p.T, :], (p.T, 1, p.J)),
(1, p.S, 1),
)
e_3D = p.e
mtry_path = tax.MTR_income(
r_p_path[: p.T],
Expand All @@ -1327,6 +1330,7 @@ def run_TPI(p, client=None):
etr_params_4D,
mtry_params_4D,
capital_noncompliance_rate_3D,
income_tax_filer_3D,
p,
)
mtrx_path = tax.MTR_income(
Expand All @@ -1340,6 +1344,7 @@ def run_TPI(p, client=None):
etr_params_4D,
mtrx_params_4D,
labor_noncompliance_rate_3D,
income_tax_filer_3D,
p,
)
etr_path = tax.ETR_income(
Expand All @@ -1352,9 +1357,9 @@ def run_TPI(p, client=None):
etr_params_4D,
labor_noncompliance_rate_3D,
capital_noncompliance_rate_3D,
income_tax_filer_3D,
p,
)

# Note that implicitly in this computation is that immigrants'
# wealth is all in the form of private capital
I_d = aggr.get_I(
Expand Down
2 changes: 1 addition & 1 deletion ogcore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@
from ogcore.txfunc import *
from ogcore.utils import *

__version__ = "0.15.2"
__version__ = "0.15.3"
56 changes: 56 additions & 0 deletions ogcore/default_parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -4304,6 +4304,62 @@
}
}
},
"income_tax_filer": {
"title": "Income tax filer indicator",
"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.",
"section_1": "Fiscal Policy Parameters",
"section_2": "Taxes",
"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.",
"type": "float",
"number_dims": 2,
"value": [
{
"value": [[
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0
]]
}
],
"validators": {
"range": {
"min": 0.0,
"max": 1.0
}
}
},
"wealth_tax_filer": {
"title": "Wealth tax filer indicator",
"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.",
"section_1": "Fiscal Policy Parameters",
"section_2": "Taxes",
"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.",
"type": "float",
"number_dims": 2,
"value": [
{
"value": [[
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0
]]
}
],
"validators": {
"range": {
"min": 0.0,
"max": 1.0
}
}
},
"nu": {
"title": "Parameter for convergence rate of functional iteration",
"description": "Parameter for convergence rate of functional iteration.",
Expand Down
22 changes: 21 additions & 1 deletion ogcore/household.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,15 +480,21 @@ def FOC_savings(
beta = p.beta[j]
if method == "SS":
tax_noncompliance = p.capital_income_tax_noncompliance_rate[-1, j]
income_tax_filer = p.income_tax_filer[-1, j]
wealth_tax_filer = p.wealth_tax_filer[-1, j]
e = np.squeeze(p.e[-1, :, j])
elif method == "TPI_scalar":
tax_noncompliance = p.capital_income_tax_noncompliance_rate[0, j]
income_tax_filer = p.income_tax_filer[0, j]
wealth_tax_filer = p.wealth_tax_filer[0, j]
e = np.squeeze(p.e[0, :, j])
else:
length = r.shape[0]
tax_noncompliance = p.capital_income_tax_noncompliance_rate[
t : t + length, j
]
income_tax_filer = p.income_tax_filer[t : t + length, j]
wealth_tax_filer = p.wealth_tax_filer[t : t + length, j]
e_long = np.concatenate(
(
p.e,
Expand All @@ -502,15 +508,21 @@ def FOC_savings(
beta = p.beta
if method == "SS":
tax_noncompliance = p.capital_income_tax_noncompliance_rate[-1, :]
income_tax_filer = p.income_tax_filer[-1, :]
wealth_tax_filer = p.wealth_tax_filer[-1, :]
e = np.squeeze(p.e[-1, :, :])
elif method == "TPI_scalar":
tax_noncompliance = p.capital_income_tax_noncompliance_rate[0, :]
income_tax_filer = p.income_tax_filer[0, :]
wealth_tax_filer = p.wealth_tax_filer[0, :]
e = np.squeeze(p.e[0, :, :])
else:
length = r.shape[0]
tax_noncompliance = p.capital_income_tax_noncompliance_rate[
t : t + length, :
]
income_tax_filer = p.income_tax_filer[t : t + length, :]
wealth_tax_filer = p.wealth_tax_filer[t : t + length, :]
e_long = np.concatenate(
(
p.e,
Expand Down Expand Up @@ -572,10 +584,11 @@ def FOC_savings(
etr_params,
mtry_params,
tax_noncompliance,
income_tax_filer,
p,
)
)
- tax.MTR_wealth(b, h_wealth, m_wealth, p_wealth)
- tax.MTR_wealth(b, h_wealth, m_wealth, p_wealth, wealth_tax_filer)
)
savings_ut = (
rho * np.exp(-p.sigma * p.g_y) * chi_b * b_splus1 ** (-p.sigma)
Expand Down Expand Up @@ -685,14 +698,17 @@ def FOC_labor(
if j is not None:
if method == "SS":
tax_noncompliance = p.labor_income_tax_noncompliance_rate[-1, j]
income_tax_filer = p.income_tax_filer[-1, j]
e = np.squeeze(p.e[-1, :, j])
elif method == "TPI_scalar":
tax_noncompliance = p.labor_income_tax_noncompliance_rate[0, j]
income_tax_filer = p.income_tax_filer[0, j]
e = np.squeeze(p.e[0, -1, j])
else:
tax_noncompliance = p.labor_income_tax_noncompliance_rate[
t : t + length, j
]
income_tax_filer = p.income_tax_filer[t : t + length, j]
e_long = np.concatenate(
(
p.e,
Expand All @@ -704,14 +720,17 @@ def FOC_labor(
else:
if method == "SS":
tax_noncompliance = p.labor_income_tax_noncompliance_rate[-1, :]
income_tax_filer = p.income_tax_filer[-1, :]
e = np.squeeze(p.e[-1, :, :])
elif method == "TPI_scalar":
tax_noncompliance = p.labor_income_tax_noncompliance_rate[0, :]
income_tax_filer = p.income_tax_filer[0, :]
e = np.squeeze(p.e[0, -1, :])
else:
tax_noncompliance = p.labor_income_tax_noncompliance_rate[
t : t + length, :
]
income_tax_filer = p.income_tax_filer[t : t + length, :]
e_long = np.concatenate(
(
p.e,
Expand Down Expand Up @@ -761,6 +780,7 @@ def FOC_labor(
etr_params,
mtrx_params,
tax_noncompliance,
income_tax_filer,
p,
)
)
Expand Down
2 changes: 2 additions & 0 deletions ogcore/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ def compute_default_params(self):
"labor_income_tax_noncompliance_rate",
"capital_income_tax_noncompliance_rate",
"replacement_rate_adjust",
"income_tax_filer",
"wealth_tax_filer",
]
for item in tp_param_list3:
param_in = getattr(self, item)
Expand Down
Loading
Loading