Skip to content

Commit d476a06

Browse files
authored
Merge pull request PSLmodels#1044 from jdebacker/replacement_rate_j
Merging
2 parents 759afbf + eadb482 commit d476a06

9 files changed

Lines changed: 40 additions & 15 deletions

File tree

ogcore/TPI.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ def inner_loop(guesses, outer_loop_vars, initial_values, ubi, j, ind, p):
420420
bq[0, -1, j],
421421
rm[0, -1, j],
422422
tr[0, -1, j],
423-
theta * p.replacement_rate_adjust[0],
423+
theta * p.replacement_rate_adjust[0, j],
424424
factor,
425425
ubi[0, -1, j],
426426
j,
@@ -436,7 +436,7 @@ def inner_loop(guesses, outer_loop_vars, initial_values, ubi, j, ind, p):
436436
ind2 = np.arange(s + 2)
437437
b_guesses_to_use = np.diag(guesses_b[: p.S, :], p.S - (s + 2))
438438
n_guesses_to_use = np.diag(guesses_n[: p.S, :], p.S - (s + 2))
439-
theta_to_use = theta[j] * p.replacement_rate_adjust[: p.S]
439+
theta_to_use = theta[j] * p.replacement_rate_adjust[: p.S, j]
440440
bq_to_use = np.diag(bq[: p.S, :, j], p.S - (s + 2))
441441
rm_to_use = np.diag(rm[: p.S, :, j], p.S - (s + 2))
442442
tr_to_use = np.diag(tr[: p.S, :, j], p.S - (s + 2))
@@ -499,7 +499,7 @@ def inner_loop(guesses, outer_loop_vars, initial_values, ubi, j, ind, p):
499499
for t in range(0, p.T):
500500
b_guesses_to_use = 0.75 * np.diag(guesses_b[t : t + p.S, :])
501501
n_guesses_to_use = np.diag(guesses_n[t : t + p.S, :])
502-
theta_to_use = theta[j] * p.replacement_rate_adjust[t : t + p.S]
502+
theta_to_use = theta[j] * p.replacement_rate_adjust[t : t + p.S, j]
503503
bq_to_use = np.diag(bq[t : t + p.S, :, j])
504504
rm_to_use = np.diag(rm[t : t + p.S, :, j])
505505
tr_to_use = np.diag(tr[t : t + p.S, :, j])

ogcore/default_parameters.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4057,16 +4057,16 @@
40574057
},
40584058
"replacement_rate_adjust": {
40594059
"title": "Adjustment to the Social Security retirement benefits replacement rate",
4060-
"description": "Adjustment to the Social Security retirement benefits replacement rate. Set value for base year, click '+' to add value for next year. All future years not specified are set to last value entered.",
4060+
"description": "Adjustment to the Social Security retirement benefits replacement rate for year t and household type j. Set value for base year, click '+' to add value for next year. All future years not specified are set to last value entered.",
40614061
"section_1": "Fiscal Policy Parameters",
40624062
"section_2": "Government Pension Parameters",
40634063
"notes": "This parameter willy only vary along the time path. It is assumed to be one in the steady state. The steady state retirement rate can be adjusted by changing the parameters of the retirement benefits function.",
40644064
"type": "float",
4065-
"number_dims": 1,
4065+
"number_dims": 2,
40664066
"value": [
40674067
{
40684068
"value": [
4069-
1.0
4069+
[1.0]
40704070
]
40714071
}
40724072
],

ogcore/parameters.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ def compute_default_params(self):
170170
"m_wealth",
171171
"p_wealth",
172172
"retirement_age",
173-
"replacement_rate_adjust",
174173
"zeta_D",
175174
"zeta_K",
176175
"r_gov_scale",
@@ -208,6 +207,7 @@ def compute_default_params(self):
208207
tp_param_list3 = [
209208
"labor_income_tax_noncompliance_rate",
210209
"capital_income_tax_noncompliance_rate",
210+
"replacement_rate_adjust",
211211
]
212212
for item in tp_param_list3:
213213
param_in = getattr(self, item)

ogcore/pensions.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,24 +168,24 @@ def SS_amount(w, n, theta, t, j, shift, method, e, p):
168168
else:
169169
retireTPI = p.retire[t] - 1 - p.S
170170
pension[retireTPI:] = (
171-
theta[j] * p.replacement_rate_adjust[t] * w[retireTPI:]
171+
theta[j] * p.replacement_rate_adjust[t, j] * w[retireTPI:]
172172
)
173173
elif len(n.shape) == 2:
174174
for tt in range(pension.shape[0]):
175175
pension[tt, retireTPI[tt] :] = (
176-
theta * p.replacement_rate_adjust[t + tt] * w[tt]
176+
theta * p.replacement_rate_adjust[t + tt, j] * w[tt]
177177
)
178178
else:
179179
for tt in range(pension.shape[0]):
180180
pension[tt, retireTPI[tt] :, :] = (
181181
theta.reshape(1, p.J)
182-
* p.replacement_rate_adjust[t + tt]
182+
* p.replacement_rate_adjust[t + tt, :].reshape(1, p.J)
183183
* w[tt]
184184
)
185185
elif method == "TPI_scalar":
186186
# The above methods won't work if scalars are used. This option
187187
# is only called by the SS_TPI_firstdoughnutring function in TPI.
188-
pension = theta * p.replacement_rate_adjust[0] * w
188+
pension = theta * p.replacement_rate_adjust[0, j] * w
189189

190190
return pension
191191

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ build-backend = "setuptools.build_meta"
1111

1212
[tool.black]
1313
line-length = 79
14-
target-version = ["py311", "py312"]
14+
target-version = ["py312", "py313"]
1515
include = '\.pyi?$'

tests/test_aggregates.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"chi_n": np.ones(2),
1717
"labor_income_tax_noncompliance_rate": [[0.0]],
1818
"capital_income_tax_noncompliance_rate": [[0.0]],
19+
"replacement_rate_adjust": [[1.0]],
1920
"eta": (np.ones((40, 2)) / (40 * 2)),
2021
"lambdas": [0.6, 0.4],
2122
"omega": np.ones((160, 40)) / 40,
@@ -58,6 +59,7 @@ def test_get_L(n, p, method, expected):
5859
"e": np.ones((40, 2)),
5960
"labor_income_tax_noncompliance_rate": [[0.0]],
6061
"capital_income_tax_noncompliance_rate": [[0.0]],
62+
"replacement_rate_adjust": [[1.0]],
6163
"eta": (np.ones((40, 2)) / (40 * 2)),
6264
"lambdas": [0.6, 0.4],
6365
"omega": np.ones((160, 40)) / 40,
@@ -140,6 +142,7 @@ def test_get_I(b_splus1, K_p1, K, p, method, expected):
140142
"e": np.ones((40, 2)),
141143
"labor_income_tax_noncompliance_rate": [[0.0]],
142144
"capital_income_tax_noncompliance_rate": [[0.0]],
145+
"replacement_rate_adjust": [[1.0]],
143146
"eta": (np.ones((40, 2)) / (40 * 2)),
144147
"lambdas": [0.6, 0.4],
145148
"omega": np.ones((160, 40)) / 40,
@@ -198,6 +201,7 @@ def test_get_B(b, p, method, PreTP, expected):
198201
"e": np.ones((40, 2)),
199202
"labor_income_tax_noncompliance_rate": [[0.0]],
200203
"capital_income_tax_noncompliance_rate": [[0.0]],
204+
"replacement_rate_adjust": [[1.0]],
201205
"eta": (np.ones((40, 2)) / (40 * 2)),
202206
"lambdas": [0.6, 0.4],
203207
"omega": np.ones((160, 40)) / 40,
@@ -1128,6 +1132,7 @@ def test_get_RM(Y, p, method, expected):
11281132
"M": 3,
11291133
"labor_income_tax_noncompliance_rate": [[0.0]],
11301134
"capital_income_tax_noncompliance_rate": [[0.0]],
1135+
"replacement_rate_adjust": [[1.0]],
11311136
"eta": (np.ones((40, 2)) / (40 * 2)),
11321137
"lambdas": [0.6, 0.4],
11331138
"omega": np.ones((160, 40)) / 40,
@@ -1178,6 +1183,7 @@ def test_get_C(c, p, method, expected):
11781183
"e": np.ones((20, 2)),
11791184
"labor_income_tax_noncompliance_rate": [[0.0]],
11801185
"capital_income_tax_noncompliance_rate": [[0.0]],
1186+
"replacement_rate_adjust": [[1.0]],
11811187
"eta": (np.ones((20, 2)) / (20 * 2)),
11821188
"lambdas": [0.6, 0.4],
11831189
"tau_bq": [0.17],
@@ -1245,7 +1251,13 @@ def test_get_C(c, p, method, expected):
12451251
"m_wealth": [1.0],
12461252
"cit_rate": [[0.2]],
12471253
"inv_tax_credit": [[0.02]],
1248-
"replacement_rate_adjust": [1.5, 1.5, 1.5, 1.6, 1.0],
1254+
"replacement_rate_adjust": [
1255+
[1.5, 1.5],
1256+
[1.5, 1.5],
1257+
[1.5, 1.5],
1258+
[1.6, 1.6],
1259+
[1.0, 1.0],
1260+
],
12491261
"delta_tau_annual": [
12501262
[float(1 - ((1 - 0.0975) ** (20 / (p3.ending_age - p3.starting_age))))]
12511263
],
@@ -1272,6 +1284,7 @@ def test_get_C(c, p, method, expected):
12721284
"e": np.ones((20, 2)),
12731285
"labor_income_tax_noncompliance_rate": [[0.0]],
12741286
"capital_income_tax_noncompliance_rate": [[0.0]],
1287+
"replacement_rate_adjust": [[1.0]],
12751288
"eta": (np.ones((20, 2)) / (20 * 2)),
12761289
"lambdas": [0.6, 0.4],
12771290
"tau_bq": [0.17],

tests/test_pensions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"lambdas": [1.0],
1515
"labor_income_tax_noncompliance_rate": [[0.0]],
1616
"capital_income_tax_noncompliance_rate": [[0.0]],
17+
"replacement_rate_adjust": [[1.0]],
1718
"J": 1,
1819
"T": 4,
1920
"chi_n": np.ones(4),
@@ -456,7 +457,7 @@ def test_deriv_NDC(args, d_NDC_expected):
456457
n_ss = np.array([0.4, 0.45, 0.4, 0.42, 0.3, 0.2, 0.2])
457458
omegas = (1 / p4.S) * np.ones(p4.S)
458459
theta = np.array([0.4, 0.4])
459-
p4.replacement_rate_adjust = np.ones(p4.T)
460+
p4.replacement_rate_adjust = np.ones((p4.T, p4.J))
460461
pension_expected_ss = [0, 0, 0, 0, 0.404, 0.396, 0.32]
461462
method = "TPI"
462463
shift = False

tests/test_tax.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"m_wealth": [4],
2424
"labor_income_tax_noncompliance_rate": [[0.0]],
2525
"capital_income_tax_noncompliance_rate": [[0.0]],
26+
"replacement_rate_adjust": [[1.0]],
2627
}
2728
p1.update_specifications(new_param_values)
2829
expected1 = np.array([0.14285714, 0.6, 0.93103448])
@@ -41,6 +42,7 @@
4142
"m_wealth": [3, 4, 3],
4243
"labor_income_tax_noncompliance_rate": [[0.0]],
4344
"capital_income_tax_noncompliance_rate": [[0.0]],
45+
"replacement_rate_adjust": [[1.0]],
4446
}
4547
p2.update_specifications(new_param_values2)
4648
expected2 = np.array([0.084615385, 0.278021978, 0.734911243])
@@ -76,6 +78,7 @@ def test_ETR_wealth(b, p, expected):
7678
"m_wealth": [5],
7779
"labor_income_tax_noncompliance_rate": [[0.0]],
7880
"capital_income_tax_noncompliance_rate": [[0.0]],
81+
"replacement_rate_adjust": [[1.0]],
7982
}
8083
p1.update_specifications(new_param_values)
8184
expected1 = np.array([0.81122449, 1.837370242, 2.173849525])
@@ -95,6 +98,7 @@ def test_ETR_wealth(b, p, expected):
9598
"m_wealth": [3, 4, 3],
9699
"labor_income_tax_noncompliance_rate": [[0.0]],
97100
"capital_income_tax_noncompliance_rate": [[0.0]],
101+
"replacement_rate_adjust": [[1.0]],
98102
}
99103
p2.update_specifications(new_param_values2)
100104
expected2 = np.array([0.165976331, 0.522436904, 1.169769966])
@@ -896,6 +900,7 @@ def test_get_biz_tax(w, Y, L, K, p_m, p, m, method, expected):
896900
p.S = 3
897901
p.labor_income_tax_noncompliance_rate = np.zeros((p.T, p.S, p.J))
898902
p.capital_income_tax_noncompliance_rate = np.zeros((p.T, p.S, p.J))
903+
p.replacement_rate_adjust = np.ones((p.T, p.J))
899904
p.lambdas = np.array([1.0])
900905
p.e = np.array([0.5, 0.45, 0.3]).reshape(3, 1)
901906
p.h_wealth = np.ones(p.T + p.S) * 1
@@ -910,13 +915,15 @@ def test_get_biz_tax(w, Y, L, K, p_m, p, m, method, expected):
910915
p3.T = 3
911916
p3.labor_income_tax_noncompliance_rate = np.zeros((p3.T, p3.S, p3.J))
912917
p3.capital_income_tax_noncompliance_rate = np.zeros((p3.T, p3.S, p3.J))
918+
p3.replacement_rate_adjust = np.ones((p3.T, p3.J))
913919
p4 = copy.deepcopy(p)
914920
p5 = copy.deepcopy(p)
915921
p5.e = np.array([[0.3, 0.2], [0.5, 0.4], [0.45, 0.3]])
916922
p5.J = 2
917923
p5.T = 3
918924
p5.labor_income_tax_noncompliance_rate = np.zeros((p5.T, p5.S, p5.J))
919925
p5.capital_income_tax_noncompliance_rate = np.zeros((p5.T, p5.S, p5.J))
926+
p5.replacement_rate_adjust = np.ones((p5.T, p5.J))
920927
p5.lambdas = np.array([0.65, 0.35])
921928
# set variables and other parameters for each case
922929
r1 = 0.04
@@ -1139,7 +1146,7 @@ def test_get_biz_tax(w, Y, L, K, p_m, p, m, method, expected):
11391146
p7.retire = (np.array([1, 2, 2])).astype(int)
11401147

11411148
p8 = copy.deepcopy(p6)
1142-
p8.replacement_rate_adjust = [1.5, 0.6, 1.0]
1149+
p8.replacement_rate_adjust = np.array([[1.5, 1.5], [0.6, 0.6], [1.0, 1.0]])
11431150

11441151
factor = 105000
11451152
ubi1 = np.zeros((p1.T, p1.S, p1.J))
@@ -1163,6 +1170,7 @@ def test_get_biz_tax(w, Y, L, K, p_m, p, m, method, expected):
11631170
"ubi_nom_65p": 500,
11641171
"labor_income_tax_noncompliance_rate": [[0.0]],
11651172
"capital_income_tax_noncompliance_rate": [[0.0]],
1173+
"replacement_rate_adjust": [[1.0]],
11661174
}
11671175
p_u.update_specifications(new_param_values_ubi)
11681176
p_u.tax_func_type = "DEP"
@@ -1298,13 +1306,15 @@ def test_get_biz_tax(w, Y, L, K, p_m, p, m, method, expected):
12981306
p12.capital_income_tax_noncompliance_rate = (
12991307
np.ones((p12.T + p12.S, p12.J)) * 0.05
13001308
)
1309+
p12.replacement_rate_adjust = np.ones((p12.T + p12.S, p12.J)) * 1.0
13011310
p13 = copy.deepcopy(p5)
13021311
p13.labor_income_tax_noncompliance_rate = (
13031312
np.ones((p13.T + p13.S, p13.J)) * 0.05
13041313
)
13051314
p13.capital_income_tax_noncompliance_rate = (
13061315
np.ones((p13.T + p13.S, p13.J)) * 0.05
13071316
)
1317+
p13.replacement_rate_adjust = np.ones((p13.T + p13.S, p13.J)) * 1.0
13081318

13091319
expected1 = np.array([0.47374766, -0.09027663, 0.03871394])
13101320
expected2 = np.array([0.20374766, -0.09027663, 0.03871394])

tests/testing_params.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"chi_b": [80, 80],
1717
"labor_income_tax_noncompliance_rate": [[0.0]],
1818
"capital_income_tax_noncompliance_rate": [[0.0]],
19+
"replacement_rate_adjust": [[1.0]],
1920
"tax_func_type": "linear",
2021
"age_specific": false,
2122
"etr_params": [[[0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2], [0.2]],

0 commit comments

Comments
 (0)