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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ OG-BRA is a Brazil country calibration of the OG-Core overlapping-generations mo
- Default suite (matches CI, skips the long example run): `uv run python -m pytest -m 'not local' -q` (or `make test`).
- Targeted (fast): `uv run python -m pytest tests/test_macro_params.py tests/test_income.py tests/test_input_output.py -q`.
- Full example run (slow, ~35 min – 2 hr): `uv run python examples/run_og_bra.py`.
- Update baseline parameters from APIs: `make new-baseline` (runs `ogbra/update_baseline.py`, requires network access, slow).

## Repo conventions

Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ help:
@echo "lint : check formatting and lint with ruff (no changes)"
@echo "coverage : generate test coverage report"
@echo "pip-package : build sdist + wheel via uv build"
@echo "new-baseline : update baseline parameters and save to json file"
@echo "documentation : build documentation using jupyter-book"


Expand Down Expand Up @@ -77,6 +78,10 @@ endif
pip-package:
uv build

.PHONY=new-baseline
new-baseline:
uv run python ogbra/update_baseline.py

.PHONY=documentation
documentation:
uv run jupyter-book clean docs/book
Expand Down
110 changes: 6 additions & 104 deletions docs/book/content/calibration/demographics.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,33 +57,12 @@ We discuss the approach to estimating fertility rates $f_{s,t}$, mortality rates

{numref}`Figure %s <FigFertRatesBRA>` was created using the [`ogcore.demographics.get_fert()`](https://github.com/PSLmodels/OG-Core/blob/master/ogcore/demographics.py#L146) function, which downloaded the data from the United National Data Portal API and plotted it in Python.[^un_data_portal]

```{code-cell} ipython3
:tags: ["hide-input", "remove-output"]
import os
import ogcore.demographics as demog
plot_path = os.path.join(os.path.abspath(''), 'images')

fert_rates, fig = demog.get_fert(
totpers=100,
min_age=0,
max_age=99,
country_id="076",
start_year=YEAR_TO_PLOT,
end_year=YEAR_TO_PLOT,
graph=True,
plot_path=None,
download_path=None,
)
plt.savefig(os.path.join(plot_path, "fert_rates.png"), dpi=300)
plt.show()
```

```{figure} ./images/fert_rates.png
---
height: 400px
name: FigFertRatesBRA
---
Brazil fertility rates by age $\left(f_s\right)$ for $E+S=100$: year 2023
Brazil fertility rates by age $\left(f_s\right)$ for $E+S=100$
```

The fertility rates in the UN data are births per 1,000 women of age-$s$. We adjust the units of those rates to represent the number of births per total population of both men and women of age-$s$.
Expand All @@ -96,37 +75,13 @@ We discuss the approach to estimating fertility rates $f_{s,t}$, mortality rates

The mortality rates are a population-weighted average of the male and female mortality rates by one-year age increments reported by United Nations. The maximum age in years in our model is truncated to 100-years old. In addition, we constrain the mortality rate to be 1.0 or 100 percent at the maximum age of 100.

```{code-cell} ipython3
:tags: ["hide-input", "remove-output"]

import matplotlib.pyplot as plt
import os
import ogcore.demographics as demog

plot_path = os.path.join(os.path.abspath(''), 'images')
mort_rates, _, fig = demog.get_mort(
totpers=100,
min_age=0,
max_age=99,
country_id="076",
start_year=YEAR_TO_PLOT,
end_year=YEAR_TO_PLOT,
graph=True,
plot_path=None,
download_path=None,
)
plt.xlabel(r"Age ($s$)")
plt.ylabel(r"Mortality rate ($\rho_s$)")
plt.savefig(os.path.join(plot_path, "mort_rates.png"), dpi=300)
plt.show()
```

```{figure} ./images/mort_rates.png
---
height: 400px
name: FigMortRatesBRA
---
Brazil mortality rates by age $\left(\rho_{s,t}\right)$ for $E+S=100$: year 2023
Brazil mortality rates by age $\left(\rho_{s,t}\right)$ for $E+S=100$
```


Expand All @@ -141,41 +96,15 @@ We discuss the approach to estimating fertility rates $f_{s,t}$, mortality rates
i_{s+1,t+1} &= \frac{\omega_{s+1,t+1} - (1 - \rho_{s,t})\omega_{s,t}}{\omega_{s+1,t}}\qquad\qquad\forall t\quad\text{and}\quad 1\leq s \leq E+S-1
```

```{code-cell} ipython3
:tags: ["hide-input", "remove-output"]
import os
import matplotlib.pyplot as plt
import ogcore.demographics as demog
plot_path = os.path.join(os.path.abspath(''), 'images')

imm_rates, fig = demog.get_imm_rates(
totpers=100,
min_age=0,
max_age=99,
fert_rates=None,
mort_rates=None,
infmort_rates=None,
pop_dist=None,
country_id="076",
start_year=YEAR_TO_PLOT,
end_year=YEAR_TO_PLOT + 50,
graph=True,
plot_path=None,
download_path=None,
)
plt.savefig(os.path.join(plot_path, "imm_rates.png"), dpi=300)
plt.show()
```

```{figure} ./images/imm_rates.png
---
height: 400px
name: FigImmRatesBRA
---
Brazil immigration rates by age $\left(i_s\right)$ for $E+S=100$: year 2023
Brazil immigration rates by age $\left(i_s\right)$ for $E+S=100$
```

We calculate our immigration rates for the consecutive-year-periods of population distribution data 2022 and 2023. The immigration rates $i_{s,t}$ that we use in our model are the the residuals described in {eq}`EqPopImmRates` implied by these two consecutive periods. {numref}`Figure %s <FigImmRatesBRA>` shows the estimated immigration rates for $E+S=100$ and given the fertility rates from Section {ref}`SecDemogFert` and the mortality rates from Section {ref}`SecDemogMort`.
We calculate our immigration rates for the consecutive-year-periods of population distribution data 2022 and 2023. The immigration rates $i_{s,t}$ that we use in our model are the the residuals described in {eq}`EqPopImmRates` implied by these two consecutive periods. {numref}`Figure %s <FigImmRatesBRA>` shows the estimated immigration rates for $E+S=100$ and given the fertility rates from Section {ref}`SecDemogFert` and the mortality rates from Section {ref}`SecDemogMort`. These immigration rates reflect Brazil's demographic profile as a country that has historically experienced moderate emigration among working-age adults.[^out_migration]

At the end of Section {ref}`SecDemogPopSSTP`, we describe a small adjustment that we make to the immigration rates after a certain number of periods in order to make computation of the transition path equilibrium of the model compute more robustly.

Expand Down Expand Up @@ -303,7 +232,7 @@ We discuss the approach to estimating fertility rates $f_{s,t}$, mortality rates
Original immigration rates vs. adjusted immigration rates to make fixed steady-state population distribution
```

The most recent year of population data come from {cite}`Census:2015` population estimates for both sexes for 2013. We those data and use the population transition matrix {eq}`EqPopLOMstatmat2` to age it to the current model year of 2015. We then use {eq}`EqPopLOMstatmat2` to generate the transition path of the population distribution over the time period of the model. {numref}`Figure %s <FigPopDistPath>` shows the progression from the 2013 population data to the fixed steady-state at period $t=120$. The time path of the growth rate of the economically active population $\tilde{g}_{n,t}$ is shown in {numref}`Figure %s <FigPopDistPath>`.
We begin with 2026 population data and use the population transition matrix {eq}`EqPopLOMstatmat2` to age it to the start year of the model (e.g., 2025 or 2026). We then use {eq}`EqPopLOMstatmat2` to generate the transition path of the population distribution over the time period of the model. {numref}`Figure %s <FigPopDistPath>` shows the progression from the 2026 population data to the fixed steady-state at period $t=120$. The time path of the growth rate of the economically active population $\tilde{g}_{n,t}$ is shown in {numref}`Figure %s <FigGrowthPath>`.

```{figure} ./images/pop_distribution.png
---
Expand All @@ -313,34 +242,6 @@ We discuss the approach to estimating fertility rates $f_{s,t}$, mortality rates
Exogenous stationary population distribution at periods along transition path
```

```{code-cell} ipython3
:tags: ["hide-input", "remove-output"]
import os
import ogcore.demographics as demog
import matplotlib.pyplot as plt
YEAR_TO_PLOT = 2023
plot_path = os.path.join(os.path.abspath(''), 'images')
fig = pp.plot_pop_growth(
p,
start_year=YEAR_TO_PLOT,
num_years_to_plot=150,
include_title=False,
path=None,
)
# Add average growth rate with this
plt.plot(
np.arange(YEAR_TO_PLOT, YEAR_TO_PLOT + 150),
np.ones(150) * np.mean(p.g_n[:150]),
linestyle="-",
linewidth=1,
color="red",
)
plt.xlabel(r"Model Period ($t$)")
plt.ylabel(r"Population Growth Rate ($g_{n,t}$)")
plt.savefig(os.path.join(plot_path, "population_growth_rates.png"), dpi=300)
plt.show()
```

```{figure} ./images/population_growth_rates.png
---
height: 500px
Expand All @@ -353,3 +254,4 @@ We discuss the approach to estimating fertility rates $f_{s,t}$, mortality rates
[^calibage_note]: Theoretically, the model works without loss of generality for $S\geq 3$. However, because we are calibrating the ages outside of the economy to be one-fourth of $S$ (e.g., ages 21 to 100 in the economy, and ages 1 to 20 outside of the economy), it is convenient for $S$ to be at least 4.
[^houseprob_note]: The parameter $\rho_s$ is the probability that a household of age $s$ dies before age $s+1$.
[^un_data_portal]: Note that you might need a UN Data Portal API token to download the data directly from the United Nations Data Portal site. But the [`demographics.py`](https://github.com/PSLmodels/OG-Core/blob/master/ogcore/demographics.py) module will take the data from a pre-downloaded site if the API token is missing or fails.
[^out_migration]: Brazil has experienced significant emigration, particularly among younger working-age adults seeking opportunities abroad. The United Nations estimates that the net emigration rate has been a persistent feature of Brazil's demographic profile since the 1980s.
Loading
Loading