PSLmodels / OG-Core

An overlapping generations model framework for evaluating fiscal policies.
https://pslmodels.github.io/OG-Core/
Creative Commons Zero v1.0 Universal
68 stars 119 forks source link

Add remittances to OG-Core #971

Closed rickecon closed 2 months ago

rickecon commented 3 months ago

This adds remittances to OG-Core and does some heavy updates to the documentation. This PR:

cc: @jdebacker

codecov-commenter commented 3 months ago

Codecov Report

Attention: Patch coverage is 83.82353% with 11 lines in your changes missing coverage. Please review.

Project coverage is 70.14%. Comparing base (92f7594) to head (30d7977). Report is 94 commits behind head on master.

Files with missing lines Patch % Lines
ogcore/TPI.py 47.61% 11 Missing :warning:
Additional details and impacted files [![Impacted file tree graph](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971/graphs/tree.svg?width=650&height=150&src=pr&token=98mQCVhspd&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels)](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels) ```diff @@ Coverage Diff @@ ## master #971 +/- ## ========================================== + Coverage 69.98% 70.14% +0.16% ========================================== Files 20 20 Lines 4977 5038 +61 ========================================== + Hits 3483 3534 +51 - Misses 1494 1504 +10 ``` | [Flag](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels) | Coverage Δ | | |---|---|---| | [unittests](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels) | `70.14% <83.82%> (+0.16%)` | :arrow_up: | Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#carryforward-flags-in-the-pull-request-comment) to find out more. | [Files with missing lines](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels) | Coverage Δ | | |---|---|---| | [ogcore/SS.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2FSS.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL1NTLnB5) | `72.48% <100.00%> (+0.50%)` | :arrow_up: | | [ogcore/\_\_init\_\_.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2F__init__.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL19faW5pdF9fLnB5) | `100.00% <100.00%> (ø)` | | | [ogcore/aggregates.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2Faggregates.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL2FnZ3JlZ2F0ZXMucHk=) | `100.00% <100.00%> (ø)` | | | [ogcore/constants.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2Fconstants.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL2NvbnN0YW50cy5weQ==) | `100.00% <ø> (ø)` | | | [ogcore/household.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2Fhousehold.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL2hvdXNlaG9sZC5weQ==) | `87.87% <100.00%> (+0.60%)` | :arrow_up: | | [ogcore/parameter\_plots.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2Fparameter_plots.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL3BhcmFtZXRlcl9wbG90cy5weQ==) | `78.34% <100.00%> (+0.05%)` | :arrow_up: | | [ogcore/parameters.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2Fparameters.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL3BhcmFtZXRlcnMucHk=) | `83.12% <100.00%> (+0.21%)` | :arrow_up: | | [ogcore/tax.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2Ftax.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL3RheC5weQ==) | `100.00% <ø> (ø)` | | | [ogcore/TPI.py](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971?src=pr&el=tree&filepath=ogcore%2FTPI.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels#diff-b2djb3JlL1RQSS5weQ==) | `36.45% <47.61%> (+0.62%)` | :arrow_up: | ... and [1 file with indirect coverage changes](https://app.codecov.io/gh/PSLmodels/OG-Core/pull/971/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PSLmodels)
rickecon commented 2 months ago

@jdebacker. I think this branch is ready for review. I think all the code changes are now working correctly. I just have to update the test_TPI.py tests, which is a little time consuming because each one of the full run tests takes an hour to run.

rickecon commented 2 months ago

@jdebacker. All the GH Action CI tests have now passed. Some of the local tests in test_TPI.py are still failing.

I have successfully run the run_ogcore_example.py script on my local machine:

Baseline SS equilibrium

SS debt =  0.625296240150551 0.007949921472992331
IO:  (1, 1) , C:  (1,)
Foreign debt holdings =  0.2501184960602204
Foreign capital holdings =  0.05620836287422404
resource constraint:  [-4.07937573e-14]
Checking constraints on capital, labor, and consumption.
    There were no violations of the constraints on labor  supply.
    There were no violations of the constraints on  consumption.
Maximum error in labor FOC =  1.0791367799356522e-13
Maximum error in savings FOC =  7.216449660063518e-14
JUST SAVED SS output to  /Users/richardevans/Docs/Economics/OSE/OG-Core/run_examples/OG-Core-Example/OUTPUT_BASELINE/SS/SS_vars.pkl

Baseline TP equilibrium (35 min, 47 sec)

Iteration: 21
    Distance: 7.501911757006711e-06
Max absolute value resource constraint error: 8.459743900193772e-07
Checking time path for violations of constraints.
Max Euler error, savings:  3.4733882436910335e-12
Max Euler error labor supply:  1.3300471835009375e-12
Time path iteration complete.

Reform SS equilibrium

SS debt =  0.6228816994331038 0.00791922336885464
IO:  (1, 1) , C:  (1,)
Foreign debt holdings =  0.24915267977324151
Foreign capital holdings =  0.05260193171249955
resource constraint:  [-2.34014197e-14]
Checking constraints on capital, labor, and consumption.
    There were no violations of the constraints on labor  supply.
    There were no violations of the constraints on  consumption.
Maximum error in labor FOC =  1.1102230246251565e-13
Maximum error in savings FOC =  8.615330671091215e-14
JUST SAVED SS output to  /Users/richardevans/Docs/Economics/OSE/OG-Core/run_examples/OG-Core-Example/OUTPUT_REFORM/SS/SS_vars.pkl

Reform TP equilibrium (39 min, 29 sec)

Iteration: 21
    Distance: 6.942822337487318e-06
Max absolute value resource constraint error: 8.089560793039796e-07
Checking time path for violations of constraints.
Max Euler error, savings:  4.652778162750337e-12
Max Euler error labor supply:  1.1874945471390674e-12
Time path iteration complete.
It took 2368.6731803417206 seconds to get that part done.
run time =  2368.6732518672943
total time was  4526.702739238739
Percentage changes in aggregates: Year                    Variable  2021  2022  2023  2024  2025  2026  2027  2028  2029  2030  2021-2030    SS
0                    GDP ($Y_t$) -0.17 -0.14 -0.22 -0.22 -0.21 -0.19 -0.16 -0.12 -0.10 -0.07      -0.16 -0.39
1            Consumption ($C_t$) -0.08  1.05  0.13 -0.13 -0.24 -0.32 -0.37 -0.42 -0.43 -0.44      -0.12 -0.72
2          Capital Stock ($K_t$) -0.37 -0.41 -0.66 -0.73 -0.75 -0.74 -0.71 -0.64 -0.60 -0.54      -0.62 -1.51
3                  Labor ($L_t$) -0.05  0.00  0.02  0.05  0.08  0.11  0.14  0.16  0.17  0.18       0.08  0.22
4     Real interest rate ($r_t$) -3.05 -2.94 -2.64 -2.52 -2.47 -2.45 -2.45 -2.58 -2.61 -2.65      -2.64 -1.40
5                      Wage rate -0.11 -0.14 -0.24 -0.27 -0.29 -0.30 -0.30 -0.28 -0.27 -0.25      -0.25 -0.61

I also plotted the aggregate remittances time series from the last two cases tested in test_aggregates.py in the test_get_RM() function. The first case, listed below as "RM2" is the following parameterization in which all the other parameters are at the default_parameters.json values:

alpha_RM_1 = 0.05
alpha_RM_T = 0.05
g_RM = ((np.exp(g_y) * (1 + g_n_ss)) - 1) * np.ones(T + S)

In this case, aggregate remittances start and end at 5% of GDP. And they grow over the time series at the aggregate long-run growth rate of the economy. The plot dips below its initial level because the long-run aggregate growth rate is bigger than the actual growth rate of GDP in the early periods.

The second lin is labeled "RM3" and is represented by a similar parameterization in which the only difference is that the growth rate of remittances over the first $T_{G1}$ periods is a half a percent greater than the long-run aggregate growth rate:

g_RM = ((np.exp(g_y) * (1 + g_n_ss)) - 1 + 0.005) * np.ones(T + S)

The code for creating this plot is:

import numpy as np
from ogcore.parameters import Specifications
from ogcore import aggregates as aggr
import matplotlib.pyplot as plt

Y_RM1 = 0.625
p_RM2= Specifications(baseline=True)
p_RM2.alpha_RM_1 = 0.05
p_RM2.alpha_RM_T = 0.05
p_RM2.g_RM =(
    ((np.exp(p_RM2.g_y_annual) * (1 + p_RM2.g_n_ss)) - 1) *
    np.ones(p_RM2.T + p_RM2.S)
)

Y_RM2 = Y_RM1 * np.ones(p_RM2.T + p_RM2.S)
RM2 = aggr.get_RM(Y_RM2, p_RM2, "TPI")

p_RM3 = copy.deepcopy(p_RM2)
p_RM3.g_RM = (
   ((np.exp(p_RM2.g_y_annual) * (1 + p_RM2.g_n_ss)) - 1 + 0.005) *
   np.ones(p_RM2.T + p_RM2.S)
)
RM3 = aggr.get_RM(Y_RM2, p_RM3, "TPI")

plt.plot(np.arange(2025, 2025 + p_RM3.T), RM3[:p_RM3.T], label='RM3')
plt.plot(np.arange(2025, 2025 + p_RM3.T), RM2[:p_RM3.T], label='RM2')
plt.vlines(
    [2025 + p_RM3.tG1, 2025 + p_RM3.tG2], 0.0292, 0.0336, color='black',
    linestyle='--'
)
plt.xlabel(r"Year $t$")
plt.ylabel(r"Remittances $\hat{RM}_t$")
plt.legend()

RMs

rickecon commented 2 months ago

@jdebacker. I think this PR is now ready for review and to be merged if accepted. In addition to running the run_ogcore_example.py script successfully as documented above, I ran all the tests--both GH Actions and local. The results are below. All the tests pass except for the 9 detailed below. And my recommendation is that we solve those remaining 9 errors in separate PRs. In summary:

tests/test_SS.py ................................... [ 6%] tests/test_TPI.py ...........F............... [ 10%] tests/test_aggregates.py ........................................ [ 17%] tests/test_basic.py .... [ 18%] tests/test_demographics.py F...FFFF..F...FF [ 21%] tests/test_elliptical_u_est.py ....... [ 22%] tests/test_execute.py . [ 22%] tests/test_firm.py ..................................................... [ 31%] ................ [ 34%] tests/test_fiscal.py ................... [ 37%] tests/test_household.py ................................................ [ 45%] .. [ 46%] tests/test_output_plots.py ............................................. [ 53%] .. [ 54%] tests/test_output_tables.py .............. [ 56%] tests/test_parameter_plots.py ........................................ [ 63%] tests/test_parameter_tables.py ....... [ 64%] tests/test_parameters.py .............. [ 67%] tests/test_pensions.py ............................... [ 72%] tests/test_run_example.py .. [ 72%] tests/test_run_ogcore.py . [ 73%] tests/test_tax.py ................................. [ 78%] tests/test_txfunc.py ............................... [ 84%] tests/test_user_inputs.py ......... [ 85%] tests/test_utils.py .................................................... [ 94%] ............................... [100%] =========================== short test summary info ============================ FAILED tests/test_TPI.py::test_run_TPI_full_run[Baseline, small open] - assert False FAILED tests/test_demographics.py::test_get_pop_objs_read_UN_data - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_demographics.py::test_imm_smooth - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_demographics.py::test_get_fert - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_demographics.py::test_get_mort - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_demographics.py::test_infant_mort - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_demographics.py::test_custom_series - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_demographics.py::test_infer_pop_nones - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_demographics.py::test_data_download - OSError: pytest: reading from stdin while output is captured! Consider usi... FAILED tests/test_run_example.py::test_run_ogcore_example - FileNotFoundError: [Errno 2] No such file or directory: '/Users/richardevan... FAILED tests/test_run_example.py::test_run_ogcore_example_output - FileNotFoundError: [Errno 2] No such file or directory: '/Users/richardevan... FAILED tests/test_txfunc.py::test_txfunc_est[DEP] - assert False FAILED tests/test_txfunc.py::test_txfunc_est[GS] - assert False FAILED tests/test_txfunc.py::test_tax_func_loop - assert False FAILED tests/test_txfunc.py::test_tax_func_estimate - assert False ======== 9 failed, 571 passed, 16801 warnings in 44933.83s (12:28:53) =========

rickecon commented 2 months ago

@jdebacker. I made the following updates:

rickecon commented 2 months ago

@jdebacker. Now all the tests are passing, both GH Actions and local (see output below). This PR should now be ready to go.

(ogcore-dev) richardevans@Richards-MacBook-Pro-2 OG-Core % pytest
============================= test session starts ==============================
platform darwin -- Python 3.12.5, pytest-8.3.2, pluggy-1.5.0
rootdir: /Users/richardevans/Docs/Economics/OSE/OG-Core
configfile: pytest.ini
testpaths: ./tests
plugins: cov-5.0.0, anyio-4.4.0, xdist-3.6.1
collected 580 items

tests/test_SS.py ...................................                     [  6%]
tests/test_TPI.py ...........................                            [ 10%]
tests/test_aggregates.py ........................................        [ 17%]
tests/test_basic.py ....                                                 [ 18%]
tests/test_demographics.py ................                              [ 21%]
tests/test_elliptical_u_est.py .......                                   [ 22%]
tests/test_execute.py .                                                  [ 22%]
tests/test_firm.py ..................................................... [ 31%]
................                                                         [ 34%]
tests/test_fiscal.py ...................                                 [ 37%]
tests/test_household.py ................................................ [ 45%]
..                                                                       [ 46%]
tests/test_output_plots.py ............................................. [ 53%]
..                                                                       [ 54%]
tests/test_output_tables.py ..............                               [ 56%]
tests/test_parameter_plots.py ........................................   [ 63%]
tests/test_parameter_tables.py .......                                   [ 64%]
tests/test_parameters.py ..............                                  [ 67%]
tests/test_pensions.py ...............................                   [ 72%]
tests/test_run_example.py ..                                             [ 72%]
tests/test_run_ogcore.py .                                               [ 73%]
tests/test_tax.py .................................                      [ 78%]
tests/test_txfunc.py ...............................                     [ 84%]
tests/test_user_inputs.py .........                                      [ 85%]
tests/test_utils.py .................................................... [ 94%]
...............................                                          [100%]
============= 580 passed, 16801 warnings in 45150.36s (12:32:30) ==============
rickecon commented 2 months ago

@jdebacker. I think this PR is ready now. All tests have passed, and I responded to all of your comments/requests.

jdebacker commented 2 months ago

@rickecon Thank you for all the work on this PR. Amazing updates to the docs and the remittances are doing to be critical for certain country calibrations. Nice job on this!