Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update demographics.py and other files #14

Merged
merged 50 commits into from
Jan 12, 2023
Merged

Conversation

rickecon
Copy link
Collaborator

@rickecon rickecon commented Nov 3, 2022

This PR:

  • updates demographics.py to use the UN population data portal data for South Africa. This only uses the population, fertility, and mortality data through 2021, which solves Issue Source demographic data from UN Population API #4 . But we could use the forecast data as well, as recommended in Issue Use UN Population forecasts in demographics.py #8. However, when I experimented with the forecast data, it looked very different from the past data.
  • adds extrapolation functions to demographics.py for the fertility rate data. The new functions are ?
  • makes minor updates to the .gitignore
  • updates the run_og_zaf.py script to include the new South Africa data in demographics.py
  • updates the calibrate.py file to include the new South Africa data in demographics.py
  • adds four UN data portal .csv files so the function does not have to download them
  • updates the macro_params.py file to comment out things we don't use and change things we don't have data for. This file still has a bunch of India calibration data. We will do a lot of work here in the next month to update the South Africa calibration.

Another note is that when I run the run_og_zaf.py script, the model stops after the first (baseline) steady-state computation because the resource constraint (the equation left out of the solution by Walra's Law) is only solved to 0.0006 precision. That is pretty precise, but it should really be arbitrarily small, like 1e-8. I need to go through the theory and why the resource constraint is not solving precisely. My hypothesis is that there is some inconsistency with how the demographics are handled between the fertility rates, mortality rates, and immigration rates versus the steady-state population distribution. I'll do more work on this. I will leave this PR as a draft (i.e., cannot be merged) until I fix this problem.

...
GE loop errors =  [-8.03523914072457e-15, -8.042178034628478e-15, 6.772360450213455e-14, 0.0, 1.3066214776813467e-12, -4.246603069191224e-15, 4.709427292581836e-13, -4.597017211338539e-15, -2.6229018956769323e-15, 4.626715677247262e-13, -3.3757718842508666e-15, -6.262351748276274e-16, 1.175934349895158e-13, -7.314981953499e-14]
Iteration: 01  Distance:  1.5534757137146956e-11
SS debt =  0.6699739181340526 0.006316971073325546
IO:  (1, 1) , C:  (1,)
Foreign debt holdings =  0.1741932187148537
Foreign capital holdings =  0.1631655427856682
resource constraint:  [0.00062941]
Resource Constraint Difference: [0.00062941]
Traceback (most recent call last):
  File "/Users/richardevans/Docs/Economics/OSE/OG-ZAF/./examples/run_og_zaf.py", line 131, in <module>
    main()
  File "/Users/richardevans/Docs/Economics/OSE/OG-ZAF/./examples/run_og_zaf.py", line 58, in main
    runner(p, time_path=True, client=client)
  File "/opt/anaconda3/envs/ogzaf-dev/lib/python3.9/site-packages/ogcore/execute.py", line 45, in runner
    ss_outputs = SS.run_SS(p, client=client)
  File "/opt/anaconda3/envs/ogzaf-dev/lib/python3.9/site-packages/ogcore/SS.py", line 1159, in run_SS
    output = SS_solver(
  File "/opt/anaconda3/envs/ogzaf-dev/lib/python3.9/site-packages/ogcore/SS.py", line 902, in SS_solver
    raise RuntimeError(err)
RuntimeError: Steady state aggregate resource constraint not satisfied

closes #4

cc: @SeaCelo

@rickecon rickecon added the enhancement New feature or request label Nov 3, 2022
@rickecon rickecon requested a review from SeaCelo November 3, 2022 08:34
@rickecon rickecon marked this pull request as draft November 3, 2022 08:34
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
SeaCelo
SeaCelo previously requested changes Nov 3, 2022
Copy link
Collaborator

@SeaCelo SeaCelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some comments and suggestions to the population, fertility, mortality, and immigration functions.

ogzaf/demographics.py Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
ogzaf/demographics.py Outdated Show resolved Hide resolved
@SeaCelo SeaCelo requested review from SeaCelo and sarvonz November 3, 2022 17:55
@SeaCelo
Copy link
Collaborator

SeaCelo commented Nov 3, 2022

@rickecon To help understand the South African population profiles, here are the detailed profiles prepared by UN Population: https://population.un.org/wpp/Graphs/DemographicProfiles/Line/710

@SeaCelo
Copy link
Collaborator

SeaCelo commented Nov 4, 2022

@rickecon To help understand the South African population profiles, here are the detailed profiles prepared by UN Population: https://population.un.org/wpp/Graphs/DemographicProfiles/Line/710

@rickecon I looked at the population trends for South Africa and the data is correct. South Africa experienced a big change in fertility and mortality due to a few causes. My quick search of the literature give some clues (preferences, risk aversion by women, HIV epidemic and mortality, etc). When we analyze the results, we will need to keep these factors in mind as the population structure has been affected by the large changes in the 2000s.

@rickecon rickecon marked this pull request as ready for review November 7, 2022 16:10
@rickecon
Copy link
Collaborator Author

rickecon commented Dec 5, 2022

@SeaCelo. I fixed the issue with the transition path equilibrium not satisfying the resource constraint in the first period. For the transition path, we have to compute the population distribution in the period before the initial period. Things like the total capital stock and total bequests in the first period depend on the population distribution in the period before that. So demographics.py produces an omega object that is the population distribution from period t=1 to period t=T+S. The module also produces omega_S_preTP, which is the population distribution in period t=0. My error was that I was taking that data from the actual data. However, the data are not consistent with the population demographics law of motion we specified in the theory, at least not with constant fertility rates and immigration rates. For this reason, I had to make omega_S_preTP consistent with the omega matrix (in terms of fertility rates, mortality rates, and immigration rates).

The baseline steady-state solution output is the following:

GE loop errors =  [-8.227446501862801e-14, -4.869021852371702e-14, -1.3922196728799463e-13, 0.0, 2.1715962361668062e-13, -1.293652684974944e-13, -5.678790770957676e-14, -5.6534638082084143e-14, -6.17214612752548e-15, -3.7567171595753734e-14, -5.0067588963642606e-14, -1.5612511283791264e-14, 1.9546864127306662e-14, 3.039235529911366e-15]
Iteration: 01  Distance:  4.784789093966305e-12
SS debt =  0.6711715191110103 0.0063955512984892274
IO:  (1, 1) , C:  (1,)
Foreign debt holdings =  0.17450459496886267
Foreign capital holdings =  0.20239138201602544
resource constraint:  [-4.2802567e-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.6076029396572267e-13
Maximum error in savings FOC =  7.638334409421077e-14
JUST SAVED SS output to  /Users/richardevans/Docs/Economics/OSE/OG-ZAF/examples/OG-ZAF-Example/OUTPUT_BASELINE/SS/SS_vars.pkl

The baseline transition path solution output is the following;

Maximum debt ratio:  1.0000000212110733
w diff:  5.364696991083662e-07 -7.536044477340909e-08
r diff:  9.654272145609433e-09 -7.871194662723013e-08
r_p diff:  9.654272145609433e-09 -7.871194662723013e-08
p_m diff:  0.0 0.0
BQ diff:  1.4075238878932805e-07 -5.199504206701566e-08
TR diff:  1.678670771831925e-07 -2.235329153860155e-07
Iteration: 22
	Distance: 6.4398646151337245e-06
Max absolute value resource constraint error: 1.0536127898710945e-05
Checking time path for violations of constraints.
Max Euler error, savings:  7.473133223356854e-12
Max Euler error labor supply:  1.9113599591946695e-12
Time path iteration complete.
It took 1815.7290947437286 seconds to get that part done.
run time =  1815.729147195816

The reform steady-state solution output is the following:

GE loop errors =  [7.81388842518993e-14, 8.174017018802715e-14, -4.771738559838923e-13, 0.0, 3.5582647939236267e-13, -2.2105581254372453e-14, -1.0152295670806666e-13, -3.642919299551295e-16, -2.207435623180487e-14, 4.0554365421385796e-14, -2.8102520310824275e-16, 2.6020852139652106e-18, 3.202299536653186e-14]
Iteration: 01  Distance:  3.1749021791539607e-12
SS debt =  1.2004356041121698 0.015262156036278306
IO:  (1, 1) , C:  (1,)
Foreign debt holdings =  0.48017424164486794
Foreign capital holdings =  0.08048294759663217
resource constraint:  [1.7069679e-14]
Steady state government spending is negative to satisfy budget
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.3011813848606835e-13
Maximum error in savings FOC =  7.149836278586008e-14
/opt/anaconda3/envs/ogzaf-dev/lib/python3.9/site-packages/ogcore/SS.py:1319: UserWarning: Warning: The combination of the tax policy you specified and your target debt-to-GDP ratio results in an infeasible amount of government spending in order to close the budget (i.e., G < 0)
  warnings.warn(
JUST SAVED SS output to  /Users/richardevans/Docs/Economics/OSE/OG-ZAF/examples/OG-ZAF-Example/OUTPUT_REFORM/SS/SS_vars.pkl

And the reform transition path solution output is the following:

Maximum debt ratio:  2.000104723711181
w diff:  2.5915477188664937e-06 -1.1417283154457891e-06
r diff:  1.3815679607981357e-07 -4.063585497746103e-07
r_p diff:  8.413844220650502e-08 -2.596077518443596e-07
p_m diff:  0.0 0.0
BQ diff:  1.1468624764796043e-07 -5.7201863237418826e-08
TR diff:  3.424993502282314e-07 -2.4845994033712016e-07
Iteration: 21
	Distance: 9.290020424167063e-06
Max absolute value resource constraint error: 6.777817169005551e-07
Checking time path for violations of constraints.
Max Euler error, savings:  9.631240249774464e-12
Max Euler error labor supply:  1.979305608301729e-12
Time path iteration complete.
It took 1644.864609003067 seconds to get that part done.
run time =  1644.8646562099457
Percentage changes in aggregates: Year                    Variable  2021  2022  ...  2030  2021-2030     SS
0                    GDP ($Y_t$)  3.71  2.09  ... -2.05      -0.58 -10.57
1            Consumption ($C_t$) 16.87  7.72  ... 12.41      12.78   6.61
2          Capital Stock ($K_t$)  1.97 -0.80  ... -5.58      -4.45 -26.04
3                  Labor ($L_t$)  0.57 -0.38  ... -4.01      -2.39  -4.80
4     Real interest rate ($r_t$)  9.35 12.07  ... 14.06      14.70  52.48
5                      Wage rate  1.05  0.41  ... -0.00      -0.17  -7.95

[6 rows x 13 columns]

@rickecon
Copy link
Collaborator Author

rickecon commented Dec 5, 2022

@SeaCelo and @sarvonz. I incorporated @sarvonz changes from his PR to my branch into this PR. However, I did it differently. For this reason, I closed his PR to my branch as well as closed his original infant mortality PR to the main repository. I decided to create a new function get_wb_infmort_rate() in demographics.py.

Copy link
Collaborator

@SeaCelo SeaCelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@SeaCelo SeaCelo dismissed their stale review December 5, 2022 21:32

outdated

@SeaCelo
Copy link
Collaborator

SeaCelo commented Dec 19, 2022

@rickecon I can't checkout this branch.

git checkout -b rickecon-demographics
git pull https://github.com/rickecon/OG-ZAF.git demog

Gives me an error:

remote: Enumerating objects: 29, done.
remote: Counting objects: 100% (14/14), done.
remote: Total 29 (delta 14), reused 14 (delta 14), pack-reused 15
Unpacking objects: 100% (29/29), 14.20 KiB | 632.00 KiB/s, done.
From https://github.com/rickecon/OG-ZAF
 * branch            demog      -> FETCH_HEAD
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint: 
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint: 
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.

I had to reset the merge with git reset --hard HEAD

@SeaCelo
Copy link
Collaborator

SeaCelo commented Dec 22, 2022

I was able to successful run the model.
FYI, these values for r_guess have a SS solution: 0.02, 0.035, 0.04, 0.06, 0.065, 0.07, 0.075, 0.08, 0.085
The default value is currently 0.045. I suggest using instead 0.04.

@SeaCelo
Copy link
Collaborator

SeaCelo commented Jan 9, 2023

@sarvonz Add your review when you have a chance please

@rickecon
Copy link
Collaborator Author

@SeaCelo and @sarvonz. This PR should have been ready to merge, but it is not. My reform steady state did not solve. This is a very rare occurrence, but I should not be surprised given the test that we ran. The steady state solution can be pretty sensitive to starting values. As such, I need to take the robustness algorithm that I built into OG-Core in PR #836 and add it to the reform steady state. My failed results from this run are below.

Baseline steady state equilibrium computation output

GE loop errors =  [-2.508410146262463e-14, -2.5070223674816816e-14, 4.933831121434196e-13, 0.0, 3.461231301571388e-12, -1.1719791803699309e-14, 4.936606678995759e-13, -1.3822276656583199e-14, -7.806255641895632e-15, 2.426600587135397e-13, 5.061367991388011e-13, -5.950101522600448e-16, 1.3844481117075702e-13, -1.092459456231154e-13]
Iteration: 01  Distance:  6.245774321886237e-12
SS debt =  1.061290349047439 0.002900917870000058
IO:  (1, 1) , C:  (1,)
Foreign debt holdings =  0.2494251742773182
Foreign capital holdings =  0.04224643260693746
resource constraint:  [2.01106493e-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 =  7.904787935331115e-14
Maximum error in savings FOC =  4.929390229335695e-14
JUST SAVED SS output to  /Users/richardevans/Docs/Economics/OSE/OG-ZAF/examples/OG-ZAF-Example/OUTPUT_BASELINE/SS/SS_vars.pkl

Baseline transition path equilibrium computation output (20 min, 12 sec)

Maximum debt ratio:  4.903478755422615
w diff:  1.5803858472995813e-06 -5.354729988304996e-07
r diff:  3.21790575019687e-08 -8.971252557499199e-08
r_p diff:  3.21790575019687e-08 -8.971252557499199e-08
p_m diff:  0.0 0.0
BQ diff:  4.3528094994388367e-07 -3.640637166735239e-08
TR diff:  1.0657384290346794e-07 -2.65468051423301e-07
Iteration: 23
	Distance: 8.970078192451272e-06
Max absolute value resource constraint error: 2.1151583345013422e-05
Checking time path for violations of constraints.
Max Euler error, savings:  8.604783552357276e-12
Max Euler error labor supply:  2.9523050670832163e-12
Time path iteration complete.
It took 1211.9648201465607 seconds to get that part done.
run time =  1211.965884923935

Reform steady state equilibrium computation output

GE loop errors =  [0.036488251251174025, 0.049594113119542794, -0.5320786226318877, 0.01524214322893791, -0.17955166455931948, 0.005327985899518087, 0.004273354336397325, -0.0005952612832190347, 0.00723037616235019, 0.024715917993280444, -0.0006519048822944025, 0.012633697617219582, -0.016159649810338753]
Traceback (most recent call last):
  File "/Users/richardevans/Docs/Economics/OSE/OG-ZAF/./examples/run_og_zaf.py", line 122, in <module>
    main()
  File "/Users/richardevans/Docs/Economics/OSE/OG-ZAF/./examples/run_og_zaf.py", line 82, in main
    runner(p2, time_path=True, client=client)
  File "/Users/richardevans/opt/anaconda3/envs/ogzaf-dev/lib/python3.9/site-packages/ogcore/execute.py", line 45, in runner
    ss_outputs = SS.run_SS(p, client=client)
  File "/Users/richardevans/opt/anaconda3/envs/ogzaf-dev/lib/python3.9/site-packages/ogcore/SS.py", line 1358, in run_SS
    raise RuntimeError("Steady state equilibrium not found")
RuntimeError: Steady state equilibrium not found

@jdebacker
Copy link
Collaborator

@rickecon This is unusual. Were you running the run_og_zaf.py script that is in the main branch?

If so, I think I see the issue. It is that with the reform parameters object, the values are set to the default from OG-Core. The code reads:

    p2 = Specifications(
        baseline=False,
        num_workers=num_workers,
        baseline_dir=base_dir,
        output_base=reform_dir,
    )
    # additional parameters to change
    updated_params_ref = {
        "cit_rate": [[0.26]],
        "debt_ratio_ss": 1.2,
    }
    p2.update_specifications(updated_params_ref)

But I think what you want is:

    p2 = Specifications(
        baseline=False,
        num_workers=num_workers,
        baseline_dir=base_dir,
        output_base=reform_dir,
    )
   p2.update_specifications(
        json.load(
            open(
                os.path.join(
                    CUR_DIR, "..", "ogzaf", "ogzaf_default_parameters.json"
                )
            )
        )
    )
    # Update parameters from calibrate.py Calibration class
    c2 = Calibration(p2)
    updated_params = c2.get_dict()
    p2.update_specifications(updated_params)
    # additional parameters to change
    updated_params_ref = {
        "cit_rate": [[0.26]],
        "debt_ratio_ss": 1.2,
    }
    p2.update_specifications(updated_params_ref)

Or (for fewer lines of code):

    p2 = copy.deepcopy(p)
    p2.baseline = False
    p2.output_base = reform_dir
    # additional parameters to change
    updated_params_ref = {
        "cit_rate": [[0.26]],
        "debt_ratio_ss": 1.2,
    }
    p2.update_specifications(updated_params_ref)

With this, the differences in parameterization between the baseline and reform will be much less and therefore the baseline solution will represent good starting values for the reform. What is currently run is just too different because you switch from ZAF demographics, policy, etc. to the OG-Core default values for those (which as more or less the USA values).

@rickecon
Copy link
Collaborator Author

OK. @jdebacker's suggestion fixed it. I updated run_og_zaf.py. The reform is now running very well. This PR is ready to merge. Below are my reform steady-state and transition path output that correspond to the baseline run in my previous comment.

Reform steady state equilibrium computation output

GE loop errors =  [6.938893903907228e-18, 6.938893903907228e-18, 0.0, 0.0, -2.220446049250313e-16, 3.469446951953614e-17, -1.4224732503009818e-15, 4.163336342344337e-17, 3.469446951953614e-17, -1.429412144204889e-15, 2.0816681711721685e-17, 3.660266534311063e-16, -6.938893903907228e-18]
Iteration: 01  Distance:  2.274998632632352e-14
SS debt =  1.269064660476182 0.0034688455944833566
IO:  (1, 1) , C:  (1,)
Foreign debt holdings =  0.298256433211293
Foreign capital holdings =  0.1677431527583257
resource constraint:  [-3.33066907e-15]
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 =  7.949196856316121e-14
Maximum error in savings FOC =  4.796163466380676e-14
JUST SAVED SS output to  /Users/richardevans/Docs/Economics/OSE/OG-ZAF/examples/OG-ZAF-Example/OUTPUT_REFORM/SS/SS_vars.pkl

Reform transition path equilibrium computation output (21 min, 25 sec)

Maximum debt ratio:  4.87467226523405
w diff:  1.5875761869565963e-06 -3.954484590895646e-07
r diff:  2.3654958110352897e-08 -9.037962634544927e-08
r_p diff:  2.3654958110352897e-08 -9.037962634544927e-08
p_m diff:  0.0 0.0
BQ diff:  4.332964183076382e-07 -3.657225344094739e-08
TR diff:  1.0994371051759044e-07 -2.6346526710296914e-07
Iteration: 23
	Distance: 8.94115225742335e-06
Max absolute value resource constraint error: 2.1143231016623742e-05
Checking time path for violations of constraints.
Max Euler error, savings:  8.690714814463263e-12
Max Euler error labor supply:  2.97939450888407e-12
Time path iteration complete.
It took 1199.5632781982422 seconds to get that part done.
run time =  1199.5642490386963
Percentage changes in aggregates: Year                    Variable  2021  2022  2023  2024  ...  2028  2029  2030  2021-2030    SS
0                    GDP ($Y_t$) -0.20 -0.20 -0.20 -0.20  ... -0.20 -0.20 -0.19      -0.20 -0.35
1            Consumption ($C_t$) -0.08 -0.13 -0.13 -0.11  ... -0.11 -0.11 -0.11      -0.11 -0.17
2          Capital Stock ($K_t$) -0.42 -0.42 -0.43 -0.43  ... -0.42 -0.42 -0.42      -0.42 -0.76
3                  Labor ($L_t$) -0.02 -0.02 -0.02 -0.02  ... -0.02 -0.02 -0.02      -0.02 -0.03
4     Real interest rate ($r_t$) -0.06 -0.06 -0.06 -0.06  ... -0.07 -0.07 -0.07      -0.06  0.34
5                      Wage rate -0.18 -0.18 -0.18 -0.18  ... -0.18 -0.18 -0.18      -0.18 -0.32

[6 rows x 13 columns]

cc: @SeaCelo @sarvonz

@SeaCelo
Copy link
Collaborator

SeaCelo commented Jan 12, 2023

@rickecon In my test it didn't find a SS solution with the default value initial_guess_r_SS = 0.045. I did get solutions for values of 0.03 and 0.055.

@rickecon
Copy link
Collaborator Author

@SeaCelo. Make sure you updated your ogzaf-dev conda environment. Your old environment might have the old version of OG-Core installed from pip.

  • conda remove --name ogzaf-dev --all
  • While in the OG-ZAF directory, re-create the conda environment: conda env create -f environment.yml
  • Activate the ogzaf-dev environment: conda activate ogzaf-dev
  • Install the ogzaf package in this environment: pip install -e .

Now run run_og_zaf.py from your version of my demog branch. Make sure that your version of my demog branch was pulled yesterday afternoon after my last commit.

If this doesn't work, let's set up a video call for sometime today for me to look at what you have. You and I have the same hardware setup. This should be working.

@SeaCelo
Copy link
Collaborator

SeaCelo commented Jan 12, 2023

Re-installing OG-CORE solved the issue and I have identical results. Merging this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Source demographic data from UN Population API
3 participants