├── .gitattributes ├── .github └── workflows │ ├── pre-commmit.yml │ ├── release.yml │ ├── rtd-link-preview.yml │ └── run_tests.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .pylintrc ├── .readthedocs.yaml ├── GCN Files ├── Baxter_King_1993.gcn ├── New_Keynesian.gcn ├── RBC.gcn ├── RBC_extended.gcn ├── RBC_two_household.gcn ├── RBC_two_household_additive.gcn ├── RBC_with_CES.gcn ├── sims_2024 │ ├── nk_complete_more_shocks.gcn │ ├── nk_complete_taxes.gcn │ ├── nk_money_growth.gcn │ ├── nk_taylor_rule.gcn │ ├── nk_taylor_rule_capital.gcn │ ├── nk_taylor_rule_fully_linear.gcn │ ├── nk_taylor_rule_linearized.gcn │ ├── nk_taylor_rule_stick_wage_capital.gcn │ └── nk_with_sticky_wages.gcn └── skilled_unskilled_rbc.gcn ├── LICENSE ├── README.md ├── codecov.yml ├── conda_envs ├── environment.yml ├── environment_dev.yml ├── environment_docs.yml └── geconpy_test.yml ├── docs ├── Makefile ├── make.bat ├── scripts │ └── rerun_examples.py └── source │ ├── _templates │ ├── autosummary │ │ └── class.rst │ ├── nb-badges.html │ ├── postcard.html │ ├── postcard_categories.html │ └── rendered_citations.html │ ├── api.rst │ ├── api │ ├── classes.rst │ ├── classes │ │ ├── containers.rst │ │ └── time_aware_symbol.rst │ ├── dynare_convert.rst │ ├── exceptions.rst │ ├── model.rst │ ├── model │ │ ├── block.rst │ │ ├── build.rst │ │ ├── compile.rst │ │ ├── model.rst │ │ ├── parameters.rst │ │ ├── perturbation.rst │ │ ├── simplification.rst │ │ ├── statespace.rst │ │ └── steady_state.rst │ ├── numbaf.rst │ ├── numbaf │ │ ├── LAPACK.rst │ │ ├── overloads.rst │ │ └── utilities.rst │ ├── parser.rst │ ├── parser │ │ ├── file_loaders.rst │ │ ├── gEcon_parser.rst │ │ ├── parse_distributions.rst │ │ ├── parse_equations.rst │ │ ├── parse_plaintext.rst │ │ └── validation.rst │ ├── plotting.rst │ ├── solvers.rst │ ├── solvers │ │ ├── cycle_reduction.rst │ │ ├── gensys.rst │ │ └── shared.rst │ └── utilities.rst │ ├── conf.py │ ├── dev │ └── index.rst │ ├── examples │ ├── GCN Files │ │ ├── RBC.gcn │ │ ├── RBC_backward_compat.gcn │ │ ├── RBC_extended.gcn │ │ ├── RBC_two_household.gcn │ │ ├── RBC_two_household_additive.gcn │ │ └── RBC_with_CES.gcn │ ├── case_study │ │ ├── multiple_households.ipynb │ │ └── production_functions.ipynb │ ├── estimation │ │ ├── estimation_example.ipynb │ │ └── fit_rbc_to_us_data.ipynb │ └── introductory │ │ ├── introduction_to_geconpy.ipynb │ │ └── time_aware_symbol.ipynb │ ├── get_started │ ├── about.rst │ ├── index.rst │ ├── install.rst │ └── overview.rst │ ├── index.rst │ ├── install.rst │ ├── release │ └── index.rst │ └── user_guide │ ├── dsge_intro.rst │ ├── estimation.rst │ ├── example_model.rst │ ├── gcn_files.rst │ └── index.rst ├── gEconpy ├── __init__.py ├── _version.py ├── classes │ ├── __init__.py │ ├── containers.py │ └── time_aware_symbol.py ├── dynare_convert.py ├── exceptions.py ├── model │ ├── __init__.py │ ├── block.py │ ├── build.py │ ├── compile.py │ ├── model.py │ ├── parameters.py │ ├── perturbation.py │ ├── simplification.py │ ├── statespace.py │ └── steady_state.py ├── numbaf │ ├── LAPACK.py │ ├── __init__.py │ ├── intrinsics.py │ ├── overloads.py │ └── utilities.py ├── parser │ ├── __init__.py │ ├── constants.py │ ├── dist_syntax.py │ ├── file_loaders.py │ ├── gEcon_parser.py │ ├── html.py │ ├── parse_distributions.py │ ├── parse_equations.py │ ├── parse_plaintext.py │ └── validation.py ├── plotting.py ├── solvers │ ├── __init__.py │ ├── cycle_reduction.py │ ├── gensys.py │ └── shared.py └── utilities.py ├── pyproject.toml ├── setup.py ├── sphinxext └── generate_gallery.py └── tests ├── .DS_Store ├── Test Answer Strings ├── test_block_deletion.txt ├── test_parse_gcn.txt └── test_split_gcn_by_blocks.txt ├── Test GCNs ├── basic_rbc.gcn ├── conflicting_assumptions.gcn ├── full_nk.gcn ├── full_nk_linear_phillips_curve.gcn ├── full_nk_no_ss.gcn ├── full_nk_partial_ss.gcn ├── one_block_1.gcn ├── one_block_1_dist.gcn ├── one_block_1_duplicate_params.gcn ├── one_block_1_duplicate_params_2.gcn ├── one_block_1_ss.gcn ├── one_block_1_ss_2shock.gcn ├── one_block_1_ss_error.gcn ├── one_block_2.gcn ├── one_block_2_no_extra.gcn ├── open_rbc.gcn ├── open_rbc_extra_params.gcn ├── open_rbc_orphan_params.gcn ├── pert_fails.gcn ├── rbc_2_block.gcn ├── rbc_2_block_partial_ss.gcn ├── rbc_2_block_ss.gcn ├── rbc_firm_capital.gcn ├── rbc_firm_capital_comparison.gcn ├── rbc_linearized.gcn ├── rbc_manually_calibrated.gcn └── rbc_with_excluded.gcn ├── __init__.py ├── dynare_outputs ├── basic_rbc_loglinear_results.mat ├── basic_rbc_results.mat ├── full_nk_results.mat ├── one_block_1_ss_results.mat └── rbc_2_block_ss_results.mat ├── test_block.py ├── test_compile.py ├── test_containers.py ├── test_distribution_parser.py ├── test_dynare_convert.py ├── test_gensys.py ├── test_model.py ├── test_model_loaders.py ├── test_parser.py ├── test_perturbation.py ├── test_plotting.py ├── test_statespace.py ├── test_steady_state.py ├── test_time_aware_symbols.py └── utilities ├── __init__.py ├── expected_matrices.py ├── load_dynare.py └── shared_fixtures.py /.gitattributes: -------------------------------------------------------------------------------- 1 | gEconpy/_version.py export-subst 2 | -------------------------------------------------------------------------------- /.github/workflows/pre-commmit.yml: -------------------------------------------------------------------------------- 1 | name: pre-commit 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: [main] 7 | 8 | jobs: 9 | pre-commit: 10 | runs-on: ubuntu-latest 11 | env: 12 | SKIP: no-commit-to-branch 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-python@v5 16 | - uses: pre-commit/action@v3.0.1 17 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release-pipeline 2 | 3 | on: 4 | release: 5 | types: 6 | - created 7 | 8 | jobs: 9 | release-job: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 13 | - name: Set up Python 14 | uses: actions/setup-python@v5 15 | with: 16 | python-version: 3.12 17 | - name: Install release tooling 18 | run: | 19 | pip install twine wheel numpy setuptools versioneer 20 | - name: Build package 21 | run: | 22 | python setup.py sdist bdist_wheel 23 | - name: Check version number match 24 | run: | 25 | echo "GITHUB_REF: ${GITHUB_REF}" 26 | # The GITHUB_REF should be something like "refs/tags/v1.2.3" 27 | # Make sure the package version is the same as the tag 28 | grep -Rq "^Version: ${GITHUB_REF:11}$" gEconpy.egg-info/PKG-INFO 29 | - uses: actions/upload-artifact@v4 30 | with: 31 | name: bdist 32 | path: dist/* 33 | pypi-publish: 34 | needs: release-job 35 | name: upload release to PyPI 36 | runs-on: ubuntu-latest 37 | permissions: 38 | id-token: write 39 | steps: 40 | - uses: actions/download-artifact@v4 41 | with: 42 | name: bdist 43 | path: dist 44 | - name: Publish package distributions to PyPI 45 | uses: pypa/gh-action-pypi-publish@release/v1 46 | test-install-job: 47 | needs: pypi-publish 48 | runs-on: ubuntu-latest 49 | steps: 50 | - name: Set up Python 51 | uses: actions/setup-python@v5 52 | with: 53 | python-version: 3.12 54 | - name: Give PyPI a chance to update the index 55 | run: sleep 360 56 | - name: Install from PyPI 57 | run: | 58 | pip install gEconpy==${GITHUB_REF:11} 59 | -------------------------------------------------------------------------------- /.github/workflows/rtd-link-preview.yml: -------------------------------------------------------------------------------- 1 | name: Read the Docs Pull Request Preview 2 | on: 3 | pull_request_target: 4 | types: 5 | - opened 6 | 7 | permissions: 8 | pull-requests: write 9 | 10 | jobs: 11 | documentation-links: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: readthedocs/actions/preview@v1 15 | with: 16 | project-slug: "gEconpy" 17 | -------------------------------------------------------------------------------- /.github/workflows/run_tests.yml: -------------------------------------------------------------------------------- 1 | name: run_tests 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: [main] 7 | 8 | 9 | # Cancels all previous workflow runs for pull requests that have not completed. 10 | concurrency: 11 | # The concurrency group contains the workflow name and the branch name for pull requests 12 | # or the commit hash for any other events. 13 | group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} 14 | cancel-in-progress: true 15 | 16 | 17 | jobs: 18 | unittest: 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | os: [ubuntu-latest, windows-latest] 23 | python-version: ["3.11", "3.12"] 24 | exclude: 25 | - os: ubuntu-latest 26 | python-version: "3.11" 27 | - os: windows-latest 28 | python-version: "3.12" 29 | test-subset: 30 | - | 31 | tests/ 32 | 33 | runs-on: ${{ matrix.os }} 34 | 35 | env: 36 | TEST_SUBSET: ${{ matrix.test-subset }} 37 | 38 | defaults: 39 | run: 40 | shell: bash -l {0} 41 | 42 | steps: 43 | - uses: actions/checkout@v3 44 | - uses: actions/cache@v3 45 | env: 46 | # Increase this value to reset cache if geconpy_test.yml has changed 47 | CACHE_NUMBER: 4 48 | with: 49 | path: ~/conda_pkgs_dir 50 | key: ${{ runner.os }}-py${{matrix.python-version}}-conda-${{ env.CACHE_NUMBER }}-${{ 51 | hashFiles('conda_envs/geconpy_test.yml') }} 52 | - name: Cache multiple paths 53 | uses: actions/cache@v3 54 | env: 55 | # Increase this value to reset cache if requirements.txt has changed 56 | CACHE_NUMBER: 4 57 | with: 58 | path: | 59 | ~/.cache/pip 60 | $RUNNER_TOOL_CACHE/Python/* 61 | ~\AppData\Local\pip\Cache 62 | key: ${{ runner.os }}-build-${{ matrix.python-version }}-${{ env.CACHE_NUMBER }}-${{ 63 | hashFiles('requirements.txt') }} 64 | - uses: conda-incubator/setup-miniconda@v2 65 | with: 66 | miniforge-variant: Miniforge3 67 | miniforge-version: latest 68 | mamba-version: "*" 69 | activate-environment: geconpy-test 70 | channel-priority: strict 71 | environment-file: conda_envs/geconpy_test.yml 72 | python-version: ${{matrix.python-version}} 73 | use-mamba: true 74 | use-only-tar-bz2: false # IMPORTANT: This may break caching of conda packages! See https://github.com/conda-incubator/setup-miniconda/issues/267 75 | 76 | - name: Install current branch 77 | run: | 78 | conda activate geconpy-test 79 | pip install -e . 80 | python --version 81 | 82 | - name: Run tests 83 | run: | 84 | python -m pytest -vv --cache-clear --cov=gEconpy --cov-report=xml --no-cov-on-fail --cov-report term $TEST_SUBSET 85 | - name: Upload coverage to Codecov 86 | uses: codecov/codecov-action@v3 87 | with: 88 | token: ${{ secrets.CODECOV_TOKEN }} # use token for more robust uploads 89 | env_vars: TEST_SUBSET 90 | name: ${{ matrix.os }} 91 | fail_ci_if_error: false 92 | verbose: true 93 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/ 2 | 3 | # Default ignored files 4 | /shelf/ 5 | /workspace.xml 6 | # GitHub Copilot persisted chat sessions 7 | /copilot/chatSessions 8 | 9 | # Jetbrains stuff 10 | .idea/ 11 | 12 | # Byte-compiled / optimized / DLL files 13 | __pycache__/ 14 | *.py[cod] 15 | *$py.class 16 | 17 | # C extensions 18 | *.so 19 | 20 | # Distribution / packaging 21 | .Python 22 | build/ 23 | develop-eggs/ 24 | dist/ 25 | downloads/ 26 | eggs/ 27 | .eggs/ 28 | lib/ 29 | lib64/ 30 | parts/ 31 | sdist/ 32 | var/ 33 | wheels/ 34 | pip-wheel-metadata/ 35 | share/python-wheels/ 36 | generated/ 37 | 38 | *.egg-info/ 39 | .installed.cfg 40 | *.egg 41 | MANIFEST 42 | 43 | # PyInstaller 44 | # Usually these files are written by a python script from a template 45 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 46 | *.manifest 47 | *.spec 48 | 49 | # Installer logs 50 | pip-log.txt 51 | pip-delete-this-directory.txt 52 | 53 | # Unit test / coverage reports 54 | htmlcov/ 55 | .tox/ 56 | .nox/ 57 | .coverage 58 | .coverage.* 59 | .cache 60 | nosetests.xml 61 | coverage.xml 62 | *.cover 63 | *.py,cover 64 | .hypothesis/ 65 | .pytest_cache/ 66 | 67 | # Translations 68 | *.mo 69 | *.pot 70 | 71 | # Django stuff: 72 | *.log 73 | local_settings.py 74 | db.sqlite3 75 | db.sqlite3-journal 76 | 77 | # Flask stuff: 78 | instance/ 79 | .webassets-cache 80 | 81 | # Scrapy stuff: 82 | .scrapy 83 | 84 | # Sphinx documentation 85 | docs/_build/ 86 | 87 | # PyBuilder 88 | target/ 89 | 90 | # Jupyter Notebook 91 | .ipynb_checkpoints 92 | 93 | # IPython 94 | profile_default/ 95 | ipython_config.py 96 | 97 | # pyenv 98 | .python-version 99 | 100 | # pipenv 101 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 102 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 103 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 104 | # install all needed dependencies. 105 | #Pipfile.lock 106 | 107 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 108 | __pypackages__/ 109 | 110 | # Celery stuff 111 | celerybeat-schedule 112 | celerybeat.pid 113 | 114 | # SageMath parsed files 115 | *.sage.py 116 | 117 | # Environments 118 | .env 119 | .venv 120 | env/ 121 | venv/ 122 | ENV/ 123 | env.bak/ 124 | venv.bak/ 125 | 126 | # Spyder project settings 127 | .spyderproject 128 | .spyproject 129 | 130 | # Rope project settings 131 | .ropeproject 132 | 133 | # mkdocs documentation 134 | /site 135 | 136 | # mypy 137 | .mypy_cache/ 138 | .dmypy.json 139 | dmypy.json 140 | 141 | # Pyre type checker 142 | .pyre/ 143 | 144 | 145 | # Dev stuff 146 | /old/ 147 | /Notebooks/ 148 | 149 | ### macOS ### 150 | # General 151 | .DS_Store 152 | .AppleDouble 153 | .LSOverride 154 | 155 | # Icon must end with two \r 156 | Icon 157 | 158 | 159 | # Thumbnails 160 | ._* 161 | 162 | # Files that might appear in the root of a volume 163 | .DocumentRevisions-V100 164 | .fseventsd 165 | .Spotlight-V100 166 | .TemporaryItems 167 | .Trashes 168 | .VolumeIcon.icns 169 | .com.apple.timemachine.donotpresent 170 | 171 | # Directories potentially created on remote AFP share 172 | .AppleDB 173 | .AppleDesktop 174 | Network Trash Folder 175 | Temporary Items 176 | .apdisk 177 | 178 | ### macOS Patch ### 179 | # iCloud generated files 180 | *.icloud 181 | 182 | ### Vim ### 183 | # Swap 184 | [._]*.s[a-v][a-z] 185 | !*.svg # comment out if you don't need vector files 186 | [._]*.sw[a-p] 187 | [._]s[a-rt-v][a-z] 188 | [._]ss[a-gi-z] 189 | [._]sw[a-p] 190 | 191 | # Session 192 | Session.vim 193 | Sessionx.vim 194 | 195 | # Temporary 196 | .netrwhist 197 | *~ 198 | # Auto-generated tag files 199 | tags 200 | # Persistent undo 201 | [._]*.un~ 202 | 203 | # End of https://www.toptal.com/developers/gitignore/api/macos,vim 204 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v5.0.0 4 | hooks: 5 | - id: check-merge-conflict 6 | - id: check-toml 7 | - id: check-yaml 8 | - id: debug-statements 9 | - id: end-of-file-fixer 10 | - id: no-commit-to-branch 11 | args: [--branch, main] 12 | - id: trailing-whitespace 13 | 14 | - repo: https://github.com/astral-sh/ruff-pre-commit 15 | rev: v0.9.10 16 | hooks: 17 | - id: ruff 18 | args: [ --fix, --unsafe-fixes, --exit-non-zero-on-fix ] 19 | exclude: | 20 | (?x)^ 21 | |gEconpy/_version.py 22 | - id: ruff-format 23 | types_or: [ python, pyi, jupyter ] 24 | 25 | - repo: https://github.com/MarcoGorelli/madforhooks 26 | rev: 0.4.1 27 | hooks: 28 | - id: no-print-statements 29 | types: [python] 30 | exclude: | 31 | (?x)^ 32 | |gEconpy/_version.py 33 | 34 | - repo: https://github.com/MarcoGorelli/absolufy-imports 35 | rev: v0.3.1 36 | hooks: 37 | - id: absolufy-imports 38 | types: [python] 39 | 40 | - repo: https://github.com/MarcoGorelli/madforhooks 41 | rev: 0.4.1 42 | hooks: 43 | - id: check-execution-order 44 | args: [--strict] 45 | - repo: local 46 | hooks: 47 | - id: notebook_name 48 | entry: '\(notebook_name\)=' 49 | language: pygrep 50 | minimum_pre_commit_version: 2.8.0 51 | name: Check notebooks do not use literally notebook_name as target 52 | types: [jupyter] 53 | 54 | - id: no-references-as-links 55 | name: Check no references that should be sphinx cross-references are urls 56 | description: >- 57 | 'A quick check to prevent urls pointing other sphinx built docs like pymc, arviz, numpy, scipy...' 58 | files: ^examples/.+\.ipynb$ 59 | exclude: > 60 | (?x)(index.md| 61 | 404.md| 62 | conf.py) 63 | entry: > 64 | (?x)(arviz-devs.github.io| 65 | pymc-experimental.readthedocs.io| 66 | docs.pymc.io| 67 | numpy.org/doc| 68 | pymc-examples.readthedocs.io| 69 | docs.python.org| 70 | xarray.pydata.org 71 | python.arviz.org| 72 | pytensor.readthedocs.io| 73 | docs.xarray.dev| 74 | www.pymc.io| 75 | docs.scipy.org/doc) 76 | language: pygrep 77 | types_or: [markdown, rst, jupyter] 78 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | sphinx: 4 | configuration: docs/source/conf.py 5 | 6 | python: 7 | install: 8 | - method: pip 9 | path: . 10 | 11 | conda: 12 | environment: "conda_envs/environment_docs.yml" 13 | 14 | build: 15 | os: "ubuntu-22.04" 16 | tools: 17 | python: "mambaforge-4.10" 18 | -------------------------------------------------------------------------------- /GCN Files/Baxter_King_1993.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | identities 4 | { 5 | tau[ss] = tau_bar; 6 | G_B[ss] = G_B_bar; 7 | I_G[ss] = I_G_bar; 8 | K_G[ss] = I_G[ss] / delta; 9 | 10 | r_G[ss] = 1 / beta; 11 | r[ss] = (1 / beta - (1 - delta)) / (1 - tau[ss]); 12 | w[ss] = (1 - theta_K) * (A_bar * K_G[ss] ^ theta_G) ^ (1 / (1 - theta_K)) * 13 | (theta_K / r[ss]) ^ (theta_K / (1 - theta_K)); 14 | Y[ss] = ((1 - tau[ss]) * w[ss] / theta_L + G_B[ss] + I_G[ss]) / 15 | (1 + (1 - theta_K) / theta_L * (1 - tau[ss]) - delta * theta_K / r[ss]); 16 | K[ss] = theta_K * Y[ss] / r[ss]; 17 | N[ss] = (1 - theta_K) * Y[ss] / w[ss]; 18 | 19 | I[ss] = delta * theta_K * Y[ss] / r[ss]; 20 | C[ss] = (1 - tau[ss]) / theta_L * (w[ss] - (1 - theta_K) * Y[ss]); 21 | L[ss] = 1 - N[ss]; 22 | 23 | U[ss] = (1 / (1 - beta)) * (log(C[ss]) + theta_L * log(L[ss])); 24 | lambda[ss] = 1 / C[ss]; 25 | lambda_L[ss] = w[ss] * (1 - tau[ss]) / C[ss]; 26 | 27 | TC[ss] = -(w[ss] * N[ss] + r[ss] * K[ss]); 28 | Div[ss] = Y[ss] + TC[ss]; 29 | TR[ss] = tau[ss] * (w[ss] * N[ss] + r[ss] * K[ss]) - G_B[ss] - I_G[ss]; 30 | }; 31 | }; 32 | 33 | block HOUSEHOLD 34 | { 35 | definitions 36 | { 37 | u[] = log(C[]) + theta_L * log(L[]); 38 | }; 39 | 40 | objective 41 | { 42 | U[] = u[] + beta * E[][U[1]]; 43 | }; 44 | 45 | controls 46 | { 47 | C[], I[], K[], L[], N[], B[]; 48 | }; 49 | 50 | constraints 51 | { 52 | C[] + I[] + B[] / r_G[] = (1 - tau[]) * (w[] * N[] + r[] * K[-1]) 53 | + B[-1] + Div[] + TR[] : lambda[]; 54 | N[] + L[] = 1 : lambda_L[]; 55 | K[] = (1 - delta) * K[-1] + I[]; 56 | }; 57 | 58 | calibration 59 | { 60 | # Real rate = 6.5% 61 | r_G[ss] = 1.065 -> beta; 62 | delta = 0.025; 63 | N[ss] = 1/3 -> theta_L; 64 | }; 65 | }; 66 | 67 | 68 | block FIRM 69 | { 70 | objective 71 | { 72 | TC[] = -(w[] * N[] + r[] * K[-1]); 73 | }; 74 | 75 | controls 76 | { 77 | N[], K[-1]; 78 | }; 79 | 80 | constraints 81 | { 82 | Y[] = A_bar * K[-1] ^ theta_K * N[] ^ (1 - theta_K) * K_G[] ^ theta_G: mc[]; 83 | }; 84 | 85 | identities 86 | { 87 | mc[] = 1; 88 | Div[] = Y[] + TC[]; 89 | }; 90 | 91 | calibration 92 | { 93 | Y[ss] = 1 -> A_bar; 94 | w[ss] = 2 -> theta_K; 95 | theta_G = 0.1; 96 | }; 97 | }; 98 | 99 | block FISCAL_AUTHORITY 100 | { 101 | definitions 102 | { 103 | spending[] = G_B[] + I_G[] + B[-1]; 104 | income[] = tau[] * (w[] * N[] + r[] * K[-1]) + B[] / r_G[]; 105 | }; 106 | identities 107 | { 108 | # Fiscal policy rules 109 | G_B[] - G_B_bar = rho_G_B * (G_B[-1] - G_B_bar) + epsilon_GB[]; 110 | I_G[] - I_G_bar = rho_I_G * (I_G[-1] - I_G_bar) + epsilon_IG[]; 111 | log(tau[] / tau_bar) = rho_tau * log(tau[-1] / tau_bar) + epsilon_tau[]; 112 | 113 | # Government budget constraint 114 | TR[] = income[] - spending[]; 115 | 116 | # # Law of motion of public capital 117 | K_G[] = (1 - delta) * K_G[-1] + I_G[]; 118 | 119 | # Zero net supply of bonds 120 | B[] = 0; 121 | }; 122 | 123 | shocks 124 | { 125 | epsilon_GB[], 126 | epsilon_IG[], 127 | epsilon_tau[]; 128 | }; 129 | 130 | calibration 131 | { 132 | rho_G_B = 0.75; 133 | rho_tau = 0.75; 134 | rho_I_G = 0.75; 135 | 136 | # Y_ss is normalized to 1, so govt spending is 0.2 + 0.22 = 0.22 137 | # and Y[] = -TC[] = w[] * N[] + r[] * K[-1] = 1, so 0.22 taxes balances the budget. 138 | G_B_bar = 0.2; 139 | I_G_bar = 0.02; 140 | tau_bar = 0.22; 141 | 142 | }; 143 | }; 144 | -------------------------------------------------------------------------------- /GCN Files/RBC.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | U[], TC[]; 4 | }; 5 | 6 | 7 | block STEADY_STATE 8 | { 9 | identities 10 | { 11 | A[ss] = 1; 12 | mc[ss] = 1; 13 | r[ss] = (1 / beta - (1 - delta)); 14 | w[ss] = (1 - alpha) * (alpha / r[ss]) ^ (alpha / (1 - alpha)); 15 | Y[ss] = (r[ss] / (r[ss] - delta * alpha)) ^ (sigma_C / (sigma_C + sigma_L)) * 16 | (w[ss] * (w[ss] / (1 - alpha)) ^ sigma_L) ^ (1 / (sigma_C + sigma_L)); 17 | 18 | I[ss] = (delta * alpha / r[ss]) * Y[ss]; 19 | C[ss] = Y[ss] ^ (-sigma_L / sigma_C) * ((1 - alpha) ^ (-sigma_L) * w[ss] ^ (1 + sigma_L)) ^ (1 / sigma_C); 20 | K[ss] = alpha * Y[ss] * mc[ss] / r[ss]; 21 | L[ss] = (1 - alpha) * Y[ss] * mc[ss] / w[ss]; 22 | 23 | U[ss] = (1 / (1 - beta)) * (C[ss] ^ (1 - sigma_C) / (1 - sigma_C) - L[ss] ^ (1 + sigma_L) / (1 + sigma_L)); 24 | lambda[ss] = C[ss] ^ (-sigma_C); 25 | TC[ss] = -(r[ss] * K[ss] + w[ss] * L[ss]); 26 | }; 27 | }; 28 | 29 | 30 | block HOUSEHOLD 31 | { 32 | definitions 33 | { 34 | u[] = (C[] ^ (1 - sigma_C) / (1 - sigma_C) - L[] ^ (1 + sigma_L) / (1 + sigma_L)); 35 | }; 36 | 37 | controls 38 | { 39 | C[], L[], I[], K[]; 40 | }; 41 | 42 | objective 43 | { 44 | U[] = u[] + beta * E[][U[1]]; 45 | }; 46 | 47 | constraints 48 | { 49 | C[] + I[] = r[] * K[-1] + w[] * L[] : lambda[]; 50 | K[] = (1 - delta) * K[-1] + I[]; 51 | }; 52 | 53 | calibration 54 | { 55 | beta ~ maxent(Beta(), lower=0.95, upper=0.999, mass=0.99) = 0.99; 56 | delta ~ maxent(Beta(), lower=0.01, upper=0.05, mass=0.99) = 0.02; 57 | 58 | sigma_C ~ maxent(Gamma(), lower=1.01, upper=10.0, mass=0.99) = 1.5; 59 | sigma_L ~ maxent(Gamma(), lower=1.000, upper=10.0, mass=0.99) = 2.0; 60 | }; 61 | }; 62 | 63 | block FIRM 64 | { 65 | controls 66 | { 67 | K[-1], L[]; 68 | }; 69 | 70 | objective 71 | { 72 | TC[] = -(r[] * K[-1] + w[] * L[]); 73 | }; 74 | 75 | constraints 76 | { 77 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 78 | }; 79 | 80 | identities 81 | { 82 | # Perfect competition 83 | mc[] = 1; 84 | }; 85 | 86 | calibration 87 | { 88 | alpha ~ maxent(Beta(), lower=0.2, upper=0.5, mass=0.99) = 0.35; 89 | }; 90 | }; 91 | 92 | block TECHNOLOGY_SHOCKS 93 | { 94 | identities 95 | { 96 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 97 | }; 98 | 99 | shocks 100 | { 101 | epsilon_A[]; 102 | }; 103 | 104 | calibration 105 | { 106 | rho_A ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.95; 107 | }; 108 | }; 109 | -------------------------------------------------------------------------------- /GCN Files/RBC_extended.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | U[], TC[], q[], K_d[]; 4 | }; 5 | 6 | block STEADY_STATE 7 | { 8 | definitions 9 | { 10 | K_to_L[ss] = (alpha * A[ss] * mc[ss] / r[ss]) ^ (1 / (1 - alpha)); 11 | }; 12 | 13 | identities 14 | { 15 | A[ss] = 1; 16 | shock_I[ss] = 1; 17 | beta[ss] = beta; 18 | Theta[ss] = Theta; 19 | z[ss] = 1; 20 | mc[ss] = 1; 21 | 22 | r[ss] = (1 / beta - (1 - delta)); 23 | w[ss] = (1 - alpha) * A[ss] * mc[ss] * K_to_L[ss] ^ alpha; 24 | L[ss] = ((A[ss] * K_to_L[ss] ^ alpha - delta * K_to_L[ss]) ^ (-sigma_C) 25 | * (1 - phi_H * beta) / (1 - phi_H) ^ sigma_C 26 | * w[ss] / Theta 27 | ) ^ (1 / (sigma_C + sigma_L)); 28 | 29 | K[ss] = K_to_L[ss] * L[ss]; 30 | K_d[ss] = z[ss] * K[ss]; 31 | Y[ss] = A[ss] * K_d[ss] ^ alpha * L[ss] ^ (1 - alpha); 32 | 33 | I[ss] = delta * K[ss]; 34 | C[ss] = Y[ss] - I[ss]; 35 | 36 | U[ss] = (1 / (1 - beta)) * (C[ss] ^ (1 - sigma_C) / (1 - sigma_C) - L[ss] ^ (1 + sigma_L) / (1 + sigma_L)); 37 | lambda[ss] = (1 - phi_H * beta) / ((1 - phi_H) * C[ss]) ^ sigma_C; 38 | q[ss] = lambda[ss]; 39 | 40 | TC[ss] = -(r[ss] * K[ss] + w[ss] * L[ss]); 41 | }; 42 | }; 43 | 44 | 45 | block HOUSEHOLD 46 | { 47 | definitions 48 | { 49 | u[] = ((C[] - phi_H * C[-1]) ^ (1 - sigma_C) / (1 - sigma_C) - Theta[] * L[] ^ (1 + sigma_L) / (1 + sigma_L)); 50 | Psi_z[] = psi_z_1 * (z[] - 1) + psi_z / 2 * (z[] - 1) ^ 2; 51 | }; 52 | 53 | controls 54 | { 55 | C[], L[], I[], K[], z[]; 56 | }; 57 | 58 | objective 59 | { 60 | U[] = u[] + beta[] * E[][U[1]]; 61 | }; 62 | 63 | constraints 64 | { 65 | C[] + I[] + Psi_z[] * K[-1] = r[] * z[] * K[-1] + w[] * L[]: lambda[]; 66 | K[] = (1 - delta) * K[-1] + I[] * (1 - gamma_I / 2 * (shock_I[] * I[] / I[-1] - 1) ^ 2) : q[]; 67 | }; 68 | 69 | identities 70 | { 71 | log(beta[]) = rho_beta * log(beta[-1]) + (1 - rho_beta) * log(beta) + epsilon_beta[]; 72 | log(shock_I[]) = rho_I * log(shock_I[-1]) + epsilon_I[]; 73 | log(Theta[]) = rho_Theta * log(Theta[-1]) + (1 - rho_Theta) * log(Theta) + epsilon_Theta[]; 74 | }; 75 | 76 | shocks 77 | { 78 | epsilon_beta[], epsilon_I[], epsilon_Theta[]; 79 | }; 80 | 81 | 82 | calibration 83 | { 84 | beta ~ maxent(Beta(), lower=0.95, upper=0.99, mass=0.99) = 0.99; 85 | delta ~ maxent(Beta(), lower=0.01, upper=0.05, mass=0.99) = 0.035; 86 | 87 | sigma_C ~ maxent(Gamma(), lower=1.5, upper=5.0, mass=0.99) = 3; 88 | sigma_L ~ maxent(Gamma(), lower=1.0, upper=5.0, mass=0.99) = 1.5; 89 | 90 | Theta ~ maxent(Gamma(), lower=0.8, upper=1.5, mass=0.99) = 1.0; 91 | gamma_I ~ maxent(Gamma(), lower=3.0, upper=10.0) = 6.32; 92 | phi_H ~ maxent(Beta(), lower=0.7, upper=0.99, mass=0.99) = 0.8; 93 | 94 | rho_beta ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 95 | rho_Theta ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 96 | rho_I ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 97 | psi_z ~ maxent(Beta(), lower=0.05, upper=0.30) = 0.169; 98 | 99 | # Choose this to be r[ss] so that z[] has no effect on the steady-state 100 | psi_z_1 = 1 / beta - (1 - delta); 101 | }; 102 | }; 103 | 104 | block FIRM 105 | { 106 | controls 107 | { 108 | K_d[], L[]; 109 | }; 110 | 111 | objective 112 | { 113 | TC[] = -(r[] * K_d[] + w[] * L[]); 114 | }; 115 | 116 | constraints 117 | { 118 | Y[] = A[] * K_d[] ^ alpha * L[] ^ (1 - alpha) : mc[]; 119 | }; 120 | 121 | identities 122 | { 123 | # Perfect competition 124 | mc[] = 1; 125 | K_d[] = z[] * K[-1]; 126 | }; 127 | 128 | calibration 129 | { 130 | alpha ~ maxent(Beta(), lower=0.2, upper=0.5, mass=0.99) = 0.35; 131 | }; 132 | }; 133 | 134 | block TECHNOLOGY_SHOCKS 135 | { 136 | identities 137 | { 138 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 139 | }; 140 | 141 | shocks 142 | { 143 | epsilon_A[]; 144 | }; 145 | 146 | calibration 147 | { 148 | rho_A ~ Beta(mu=0.95, sigma=0.04) = 0.95; 149 | }; 150 | }; 151 | -------------------------------------------------------------------------------- /GCN Files/RBC_two_household.gcn: -------------------------------------------------------------------------------- 1 | assumptions 2 | { 3 | positive 4 | { 5 | Y[], K[], C_NR[], C_R[], 6 | w[], r[], 7 | L[], L_NR[], L_R[], 8 | TFP[], 9 | alpha, beta, sigma_C, sigma_L, delta, omega; 10 | }; 11 | }; 12 | 13 | tryreduce 14 | { 15 | U_NR[], U_R[], TC[]; 16 | }; 17 | 18 | block STEADY_STATE 19 | { 20 | identities 21 | { 22 | TFP[ss] = 1.0; 23 | shock_beta_R[ss] = 1.0; 24 | 25 | r[ss] = 1 / beta - (1 - delta); 26 | w[ss] = (1 - alpha) * (alpha / r[ss]) ^ (alpha / (1 - alpha)); 27 | mc[ss] = 1; 28 | Y[ss] = (r[ss] / (r[ss] - delta * alpha)) ^ (sigma_C / (sigma_C + sigma_L)) * 29 | (w[ss] * (w[ss] / (1 - alpha)) ^ sigma_L) ^ (1 / (sigma_C + sigma_L)); 30 | 31 | I[ss] = (delta * alpha / r[ss]) * Y[ss]; 32 | C[ss] = Y[ss] ^ (-sigma_L / sigma_C) * ((1 - alpha) ^ (-sigma_L) * w[ss] ^ (1 + sigma_L)) ^ (1 / sigma_C); 33 | K[ss] = alpha * Y[ss] * mc[ss] / r[ss]; 34 | L[ss] = (1 - alpha) * Y[ss] * mc[ss] / w[ss]; 35 | 36 | TC[ss] = -(r[ss] * K[ss] + w[ss] * L[ss]); 37 | }; 38 | }; 39 | 40 | block RICARDIAN_HOUSEHOLD 41 | { 42 | definitions 43 | { 44 | u_R[] = shock_beta_R[] * (C_R[] ^ (1 - sigma_C) / (1 - sigma_C) - 45 | L_R[] ^ (1 + sigma_L) / (1 + sigma_L)); 46 | }; 47 | 48 | controls 49 | { 50 | C_R[], L_R[], I[], K[]; 51 | }; 52 | 53 | objective 54 | { 55 | U_R[] = u_R[] + beta * E[][U_R[1]]; 56 | }; 57 | 58 | constraints 59 | { 60 | @exclude 61 | C_R[] + I[] = r[] * K[-1] + w[] * L_R[] : lambda_R[]; 62 | 63 | K[] = (1 - delta) * K[-1] + I[]: q[]; 64 | }; 65 | 66 | identities 67 | { 68 | log(shock_beta_R[]) = rho_beta_R * log(shock_beta_R[-1]) + epsilon_beta_R[]; 69 | }; 70 | 71 | shocks 72 | { 73 | epsilon_beta_R[]; 74 | }; 75 | 76 | calibration 77 | { 78 | beta = 0.99; 79 | delta = 0.02; 80 | sigma_C = 1.5; 81 | sigma_L = 2.0; 82 | rho_beta_R = 0.95; 83 | }; 84 | }; 85 | 86 | block NON_RICARDIAN_HOUSEHOLD 87 | { 88 | definitions 89 | { 90 | u_NR[] = (C_NR[] ^ (1 - sigma_C) / (1 - sigma_C) - 91 | L_NR[] ^ (1 + sigma_L) / (1 + sigma_L)); 92 | }; 93 | 94 | controls 95 | { 96 | C_NR[], L_NR[]; 97 | }; 98 | 99 | objective 100 | { 101 | U_NR[] = u_NR[] + beta * E[][U_NR[1]]; 102 | }; 103 | 104 | constraints 105 | { 106 | C_NR[] = w[] * L_NR[]: lambda_NR[]; 107 | }; 108 | }; 109 | 110 | 111 | block FIRM 112 | { 113 | controls 114 | { 115 | K[-1], L[]; 116 | }; 117 | 118 | objective 119 | { 120 | TC[] = -(r[] * K[-1] + w[] * L[]); 121 | }; 122 | 123 | constraints 124 | { 125 | Y[] = TFP[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 126 | }; 127 | 128 | identities 129 | { 130 | # Perfect competition 131 | mc[] = 1; 132 | 133 | # Exogenous technology process 134 | log(TFP[]) = rho_TFP * log(TFP[-1]) + epsilon_TFP[]; 135 | }; 136 | 137 | shocks 138 | { 139 | epsilon_TFP[]; 140 | }; 141 | 142 | calibration 143 | { 144 | alpha = 0.35; 145 | 146 | rho_TFP = 0.95; 147 | }; 148 | }; 149 | 150 | block EQULIBRIUM 151 | { 152 | identities 153 | { 154 | Y[] = C[] + I[]; 155 | L[] = omega * L_R[] + (1 - omega) * L_NR[]; 156 | C[] = omega * C_R[] + (1 - omega) * C_NR[]; 157 | }; 158 | 159 | calibration 160 | { 161 | omega = 0.5; 162 | }; 163 | }; 164 | -------------------------------------------------------------------------------- /GCN Files/RBC_two_household_additive.gcn: -------------------------------------------------------------------------------- 1 | assumptions 2 | { 3 | positive 4 | { 5 | Y[], K[], C_NR[], C_R[], 6 | w[], r[], 7 | L[], L_NR[], L_R[], 8 | TFP[], 9 | alpha, alpha_L, beta, sigma_C, sigma_L, delta; 10 | }; 11 | }; 12 | 13 | tryreduce 14 | { 15 | U_NR[], U_R[], TC[]; 16 | }; 17 | 18 | block STEADY_STATE 19 | { 20 | definitions 21 | { 22 | # Capital/Labor ratio, N = K/L 23 | N[ss] = (alpha * TFP[ss] / r[ss]) ^ (1 / (1 - alpha)); 24 | 25 | }; 26 | identities 27 | { 28 | TFP[ss] = 1.0; 29 | shock_beta_R[ss] = 1.0; 30 | Theta_R[ss] = Theta_R; 31 | Theta_N[ss] = Theta_N; 32 | 33 | r[ss] = 1 / beta - (1 - delta); 34 | w[ss] = (1 - alpha) * N[ss] ^ alpha; 35 | 36 | C_R[ss] = (w[ss] / Theta_R) ^ (1 / sigma_R); 37 | C_NR[ss] = (w[ss] / Theta_N) ^ (1 / sigma_N); 38 | 39 | C[ss] = omega * C_R[ss] + (1 - omega) * C_NR[ss]; 40 | L[ss] = C[ss] / (N[ss] ^ alpha - delta * N[ss]); 41 | L_NR[ss] = C_NR[ss] / w[ss]; 42 | L_R[ss] = (L[ss] - (1 - omega) * L_NR[ss]) / omega; 43 | 44 | K[ss] = N[ss] * L[ss]; 45 | I[ss] = delta * K[ss]; 46 | Y[ss] = C[ss] + I[ss]; 47 | 48 | lambda_R[ss] = C_R[ss] ^ -sigma_R; 49 | lambda_NR[ss] = C_NR[ss] ^ -sigma_N; 50 | q[ss] = lambda_R[ss]; 51 | }; 52 | }; 53 | 54 | block RICARDIAN_HOUSEHOLD 55 | { 56 | definitions 57 | { 58 | u_R[] = shock_beta_R[] * (C_R[] ^ (1 - sigma_R) / (1 - sigma_R) - Theta_R[] * L_R[]); 59 | }; 60 | 61 | controls 62 | { 63 | C_R[], L_R[], I[], K[]; 64 | }; 65 | 66 | objective 67 | { 68 | U_R[] = u_R[] + beta * E[][U_R[1]]; 69 | }; 70 | 71 | constraints 72 | { 73 | @exclude 74 | C_R[] + I[] = r[] * K[-1] + w[] * L_R[] : lambda_R[]; 75 | 76 | K[] = (1 - delta) * K[-1] + I[]: q[]; 77 | }; 78 | 79 | identities 80 | { 81 | log(shock_beta_R[]) = rho_beta_R * log(shock_beta_R[-1]) + epsilon_beta_R[]; 82 | log(Theta_R[]) = (1 - rho_Theta_R) * log(Theta_R) + rho_Theta_R * log(Theta_R[-1]) + epsilon_Theta_R[]; 83 | }; 84 | 85 | shocks 86 | { 87 | epsilon_beta_R[], epsilon_Theta_R[]; 88 | }; 89 | 90 | calibration 91 | { 92 | beta ~ maxent(Beta(), lower=0.90, upper=0.99) = 0.99; 93 | delta ~ maxent(Beta(), lower=0.01, upper=0.05) = 0.02; 94 | sigma_R ~ maxent(Gamma(), lower=1.1, upper=3.0) = 1.5; 95 | Theta_R ~ maxent(Gamma(), lower=0.1, upper=5.0) = 1.0; 96 | rho_beta_R ~ maxent(Beta(), lower=0.5, upper=0.99) = 0.95; 97 | rho_Theta_R ~ maxent(Beta(), lower=0.5, upper=0.99) = 0.95; 98 | }; 99 | }; 100 | 101 | block NON_RICARDIAN_HOUSEHOLD 102 | { 103 | definitions 104 | { 105 | u_NR[] = C_NR[] ^ (1 - sigma_N) / (1 - sigma_N) - Theta_N[] * L_NR[]; 106 | }; 107 | 108 | controls 109 | { 110 | C_NR[], L_NR[]; 111 | }; 112 | 113 | objective 114 | { 115 | U_NR[] = u_NR[] + beta * E[][U_NR[1]]; 116 | }; 117 | 118 | constraints 119 | { 120 | C_NR[] = w[] * L_NR[]: lambda_NR[]; 121 | }; 122 | 123 | identities 124 | { 125 | log(Theta_N[]) = (1 - rho_Theta_N) * log(Theta_N) + rho_Theta_N * log(Theta_N[-1]) + epsilon_Theta_N[]; 126 | }; 127 | 128 | shocks 129 | { 130 | epsilon_Theta_N[]; 131 | }; 132 | 133 | calibration 134 | { 135 | Theta_N ~ maxent(Gamma(), lower=0.1, upper=5.0) = 1.0; 136 | sigma_N ~ maxent(Gamma(), lower=1.1, upper=3.0) = 1.5; 137 | 138 | rho_Theta_N ~ maxent(Beta(), lower=0.5, upper=0.99) = 0.95; 139 | }; 140 | }; 141 | 142 | 143 | block FIRM 144 | { 145 | controls 146 | { 147 | K[-1], L[]; 148 | }; 149 | 150 | objective 151 | { 152 | TC[] = -(r[] * K[-1] + w[] * L[]); 153 | }; 154 | 155 | constraints 156 | { 157 | Y[] = TFP[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 158 | }; 159 | 160 | identities 161 | { 162 | # Perfect competition 163 | mc[] = 1; 164 | 165 | # Exogenous technology process 166 | log(TFP[]) = rho_TFP * log(TFP[-1]) + epsilon_TFP[]; 167 | }; 168 | 169 | shocks 170 | { 171 | epsilon_TFP[]; 172 | }; 173 | 174 | calibration 175 | { 176 | alpha ~ maxent(Beta(), lower=0.3, upper=0.6) = 0.35; 177 | rho_TFP ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.95; 178 | }; 179 | }; 180 | 181 | block EQULIBRIUM 182 | { 183 | identities 184 | { 185 | Y[] = C[] + I[]; 186 | L[] = omega * L_R[] + (1 - omega) * L_NR[]; 187 | C[] = omega * C_R[] + (1 - omega) * C_NR[]; 188 | }; 189 | 190 | calibration 191 | { 192 | omega ~ maxent(Beta(), lower=0.6, upper=0.99) = 0.66; 193 | }; 194 | }; 195 | -------------------------------------------------------------------------------- /GCN Files/RBC_with_CES.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | U[], TC[]; 4 | }; 5 | 6 | assumptions 7 | { 8 | positive 9 | { 10 | A[], Y[], C[], K[], L[], w[], r[], mc[], beta, delta, sigma_C, sigma_L, alpha, psi; 11 | }; 12 | }; 13 | 14 | block STEADY_STATE 15 | { 16 | definitions 17 | { 18 | f1[ss] = r[ss] ^ (psi - 1) * alpha ^ ((1 - psi) / psi) * (A[ss] * mc[ss]) ^ (1 - psi); 19 | N[ss] = ((f1[ss] - alpha ^ (1 / psi)) / (1 - alpha) ^ (1 / psi)) ^ (psi / (1 - psi)); 20 | f2[ss] = alpha ^ (1 / psi) * N[ss] ^ ((psi - 1) / psi) + (1 - alpha) ^ (1 / psi); 21 | }; 22 | 23 | identities 24 | { 25 | A[ss] = 1.0; 26 | r[ss] = 1 / beta - (1 - delta); 27 | mc[ss] = 1.0; 28 | 29 | w[ss] = (1 - alpha) ^ (1 / psi) * A[ss] * mc[ss] * f2[ss] ^ (1 / (psi - 1)); 30 | 31 | L[ss] = (w[ss] / Theta) ^ (1 / (sigma_L + sigma_C)) * 32 | (A[ss] * f2[ss] ^ (psi / (psi - 1)) - delta * N[ss]) ^ (-sigma_C / (sigma_L + sigma_C)); 33 | 34 | K[ss] = N[ss] * L[ss]; 35 | I[ss] = delta * K[ss]; 36 | Y[ss] = A[ss] * (alpha ^ (1 / psi) * K[ss] ^ ((psi - 1) / psi) + 37 | (1 - alpha) ^ (1 / psi) * L[ss] ^ ((psi - 1) / psi)) ^ (psi / (psi - 1)); 38 | C[ss] = Y[ss] - I[ss]; 39 | 40 | lambda[ss] = C[ss] ^ (-sigma_C); 41 | }; 42 | 43 | }; 44 | 45 | block HOUSEHOLD 46 | { 47 | definitions 48 | { 49 | u[] = C[] ^ (1 - sigma_C) / (1 - sigma_C) - Theta * L[] ^ (1 + sigma_L) / (1 + sigma_L); 50 | }; 51 | 52 | controls 53 | { 54 | C[], L[], I[], K[]; 55 | }; 56 | 57 | objective 58 | { 59 | U[] = u[] + beta * E[][U[1]]; 60 | }; 61 | 62 | constraints 63 | { 64 | C[] + I[] = r[] * K[-1] + w[] * L[] : lambda[]; 65 | 66 | K[] = (1 - delta) * K[-1] + I[]; 67 | }; 68 | 69 | calibration 70 | { 71 | beta = 0.99; 72 | delta = 0.02; 73 | sigma_C = 1.5; 74 | sigma_L = 2.0; 75 | Theta = 1.0; 76 | }; 77 | }; 78 | 79 | block FIRM 80 | { 81 | controls 82 | { 83 | K[-1], L[]; 84 | }; 85 | 86 | objective 87 | { 88 | TC[] = -(r[] * K[-1] + w[] * L[]); 89 | }; 90 | 91 | constraints 92 | { 93 | Y[] = A[] * (alpha ^ (1 / psi) * K[-1] ^ ((psi - 1) / psi) + 94 | (1 - alpha) ^ (1 / psi) * L[] ^ ((psi - 1) / psi) 95 | ) ^ (psi / (psi - 1)): mc[]; 96 | }; 97 | 98 | identities 99 | { 100 | # Perfect competition 101 | mc[] = 1; 102 | }; 103 | 104 | calibration 105 | { 106 | alpha = 0.35; 107 | psi = 0.6; 108 | }; 109 | }; 110 | 111 | block TECHNOLOGY_SHOCKS 112 | { 113 | identities 114 | { 115 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 116 | }; 117 | 118 | shocks 119 | { 120 | epsilon_A[]; 121 | }; 122 | 123 | calibration 124 | { 125 | rho_A = 0.95; 126 | }; 127 | }; 128 | -------------------------------------------------------------------------------- /GCN Files/sims_2024/nk_money_growth.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | TC[], U[], Y_j[], T[], D[]; 4 | }; 5 | 6 | 7 | block STEADY_STATE 8 | { 9 | identities 10 | { 11 | A[ss] = 1; 12 | g_M[ss] = g_M; 13 | 14 | pi[ss] = exp(g_M); 15 | SDF[ss] = beta; 16 | 17 | i[ss] = pi[ss] / beta - 1; 18 | 19 | P_reset[ss] = ((1 - phi * pi[ss] ^ (epsilon - 1)) / (1 - phi)) ^ (1 / (1 - epsilon)); 20 | 21 | mc[ss] = (epsilon - 1) / epsilon * P_reset[ss] * 22 | (1 - phi * beta * pi[ss] ^ epsilon) / (1 - phi * beta * pi[ss] ^ (epsilon - 1)); 23 | w[ss] = mc[ss] * A[ss]; 24 | 25 | nu_p[ss] = (1 - phi) * P_reset[ss] ^ (-epsilon) / (1 - phi * pi[ss] ^ epsilon); 26 | 27 | N[ss] = (nu_p[ss] ^ sigma * mc[ss] / theta) ^ (1 / (sigma + chi)); 28 | Y[ss] = N[ss] / nu_p[ss]; 29 | C[ss] = Y[ss]; 30 | lambda[ss] = C[ss] ^ (-sigma); 31 | m[ss] = psi * ((1 + i[ss]) / i[ss]) * C[ss] ^ sigma; 32 | # m[ss] = psi * C[ss] ^ sigma * ((1 + i[ss]) / i[ss]); 33 | 34 | X_hat_1[ss] = mc[ss] * Y[ss] / (1 - phi * beta * pi[ss] ^ epsilon); 35 | X_hat_2[ss] = Y[ss] / (1 - beta * phi * pi[ss] ^ (epsilon - 1)); 36 | }; 37 | }; 38 | 39 | block HOUSEHOLD 40 | { 41 | 42 | definitions 43 | { 44 | u[] = C[] ^ (1 - sigma) / (1 - sigma) - theta * N[] ^ (1 + chi) / (1 + chi) + psi * log(m[]); 45 | }; 46 | 47 | objective 48 | { 49 | U[] = u[] + beta * E[][U[1]]; 50 | }; 51 | 52 | controls 53 | { 54 | C[], N[], m[], B[]; 55 | }; 56 | 57 | constraints 58 | { 59 | @exclude 60 | C[] + B[] + m[] - m[-1] / pi[] = w[] * N[] + (1 + i[-1]) * B[-1] / pi[] - T[] + D[]: lambda[]; 61 | }; 62 | 63 | identities 64 | { 65 | SDF[] = beta * lambda[] / lambda[-1]; 66 | }; 67 | 68 | calibration 69 | { 70 | beta ~ maxent(Beta(), lower=0.95, upper=0.99) = 0.99; 71 | sigma ~ maxent(Gamma(), lower=1.5, upper=5.0) = 3; 72 | theta ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 73 | chi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 74 | psi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 75 | }; 76 | 77 | }; 78 | 79 | block INTERMEDIATE_FIRM 80 | { 81 | objective 82 | { 83 | TC[] = -(w[] * N[]); 84 | }; 85 | 86 | controls 87 | { 88 | N[]; 89 | }; 90 | 91 | constraints 92 | { 93 | Y_j[] = A[] * N[] : mc[]; 94 | }; 95 | 96 | identities 97 | { 98 | D[] = Y_j[] + TC[]; 99 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 100 | }; 101 | 102 | shocks 103 | { 104 | epsilon_A[]; 105 | }; 106 | 107 | calibration 108 | { 109 | rho_A ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 110 | }; 111 | 112 | }; 113 | 114 | block FINAL_GOODS 115 | { 116 | identities 117 | { 118 | # Reset price 119 | P_reset[] = epsilon / (epsilon - 1) * X_hat_1[] / X_hat_2[] + epsilon_markup[]; 120 | X_hat_1[] = mc[] * Y[] + phi * E[][SDF[1] * pi[1] ^ epsilon * X_hat_1[1]]; 121 | X_hat_2[] = Y[] + phi * E[][SDF[1] * pi[1] ^ (epsilon - 1) * X_hat_2[1]]; 122 | 123 | # Price index 124 | 1 = (1 - phi) * P_reset[] ^ (1 - epsilon) + phi * pi[] ^ (epsilon - 1); 125 | 126 | # Price distortion index 127 | nu_p[] = (1 - phi) * P_reset[] ^ (-epsilon) + phi * pi[] ^ epsilon * nu_p[-1]; 128 | 129 | # Aggregate production 130 | Y_j[] = nu_p[] * Y[]; 131 | }; 132 | 133 | calibration 134 | { 135 | phi ~ maxent(Beta(), lower=0.6, upper=0.9) = 3/4; 136 | epsilon ~ maxent(Gamma(), lower=2, upper=20) = 11; 137 | }; 138 | 139 | shocks 140 | { 141 | epsilon_markup[]; 142 | }; 143 | }; 144 | 145 | block GOVERNMENT 146 | { 147 | identities 148 | { 149 | g_M[] = (1 - rho_M) * g_M + rho_M * g_M[-1] + epsilon_M[]; 150 | g_M[] = log(m[]) - log(m[-1]) + log(pi[]); 151 | i[-1] * B[-1] / pi[] = T[] + m[] - m[-1] / pi[] + B[] - B[-1] / pi[]; 152 | B[] = 0; 153 | }; 154 | 155 | shocks 156 | { 157 | epsilon_M[]; 158 | }; 159 | 160 | calibration 161 | { 162 | g_M = 0.0; 163 | rho_M ~ maxent(Beta(), lower=0.3, upper=0.9) = 0.5; 164 | }; 165 | }; 166 | 167 | block EQULIBRIUM 168 | { 169 | identities 170 | { 171 | Y[] = C[]; 172 | }; 173 | }; 174 | -------------------------------------------------------------------------------- /GCN Files/sims_2024/nk_taylor_rule.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | TC[], U[], Y_j[], T[], D[]; 4 | }; 5 | 6 | 7 | block STEADY_STATE 8 | { 9 | identities 10 | { 11 | A[ss] = 1; 12 | interest_shock[ss] = 1; 13 | pi[ss] = pi_bar; 14 | epsilon_tv[ss] = epsilon; 15 | 16 | SDF[ss] = beta; 17 | 18 | i[ss] = pi[ss] / beta - 1; 19 | 20 | P_reset[ss] = ((1 - phi * pi[ss] ^ (epsilon - 1)) / (1 - phi)) ^ (1 / (1 - epsilon)); 21 | 22 | mc[ss] = (epsilon - 1) / epsilon * P_reset[ss] * 23 | (1 - phi * beta * pi[ss] ^ epsilon) / (1 - phi * beta * pi[ss] ^ (epsilon - 1)); 24 | w[ss] = mc[ss] * A[ss]; 25 | 26 | nu_p[ss] = (1 - phi) * P_reset[ss] ^ (-epsilon) / (1 - phi * pi[ss] ^ epsilon); 27 | 28 | N[ss] = (nu_p[ss] ^ sigma * mc[ss] / theta) ^ (1 / (sigma + chi)); 29 | Y[ss] = N[ss] / nu_p[ss]; 30 | C[ss] = Y[ss]; 31 | lambda[ss] = C[ss] ^ (-sigma); 32 | m[ss] = psi * ((1 + i[ss]) / i[ss]) * C[ss] ^ sigma; 33 | 34 | X_hat_1[ss] = mc[ss] * Y[ss] / (1 - phi * beta * pi[ss] ^ epsilon); 35 | X_hat_2[ss] = Y[ss] / (1 - beta * phi * pi[ss] ^ (epsilon - 1)); 36 | }; 37 | }; 38 | 39 | block HOUSEHOLD 40 | { 41 | 42 | definitions 43 | { 44 | u[] = C[] ^ (1 - sigma) / (1 - sigma) - theta * N[] ^ (1 + chi) / (1 + chi) + psi * log(m[]); 45 | }; 46 | 47 | objective 48 | { 49 | U[] = u[] + beta * E[][U[1]]; 50 | }; 51 | 52 | controls 53 | { 54 | C[], N[], m[], B[]; 55 | }; 56 | 57 | constraints 58 | { 59 | @exclude 60 | C[] + B[] + m[] - m[-1] / pi[] = w[] * N[] + (1 + i[-1]) * B[-1] / pi[] - T[] + D[]: lambda[]; 61 | }; 62 | 63 | identities 64 | { 65 | SDF[] = beta * lambda[] / lambda[-1]; 66 | }; 67 | 68 | calibration 69 | { 70 | beta ~ maxent(Beta(), lower=0.95, upper=0.99) = 0.99; 71 | sigma ~ maxent(Gamma(), lower=1.5, upper=5.0) = 3; 72 | theta ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 73 | chi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 74 | psi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 75 | }; 76 | 77 | }; 78 | 79 | block INTERMEDIATE_FIRM 80 | { 81 | objective 82 | { 83 | TC[] = -(w[] * N[]); 84 | }; 85 | 86 | controls 87 | { 88 | N[]; 89 | }; 90 | 91 | constraints 92 | { 93 | Y_j[] = A[] * N[] : mc[]; 94 | }; 95 | 96 | identities 97 | { 98 | D[] = Y_j[] + TC[]; 99 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 100 | }; 101 | 102 | shocks 103 | { 104 | epsilon_A[]; 105 | }; 106 | 107 | calibration 108 | { 109 | rho_A ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 110 | }; 111 | 112 | }; 113 | 114 | block FINAL_GOODS 115 | { 116 | identities 117 | { 118 | # Reset price 119 | P_reset[] = epsilon_tv[] / (epsilon_tv[] - 1) * X_hat_1[] / X_hat_2[]; 120 | X_hat_1[] = mc[] * Y[] + phi * E[][SDF[1] * pi[1] ^ epsilon_tv[1] * X_hat_1[1]]; 121 | X_hat_2[] = Y[] + phi * E[][SDF[1] * pi[1] ^ (epsilon_tv[1] - 1) * X_hat_2[1]]; 122 | 123 | # Price index 124 | 1 = (1 - phi) * P_reset[] ^ (1 - epsilon_tv[]) + phi * pi[] ^ (epsilon_tv[] - 1); 125 | 126 | # Price distortion index 127 | nu_p[] = (1 - phi) * P_reset[] ^ (-epsilon_tv[]) + phi * pi[] ^ epsilon_tv[] * nu_p[-1]; 128 | 129 | # Aggregate production 130 | Y_j[] = nu_p[] * Y[]; 131 | 132 | # Time varying markup 133 | log(epsilon_tv[]) = (1 - rho_markup) * log(epsilon) + rho_markup * log(epsilon_tv[-1]) - epsilon_markup[]; 134 | }; 135 | 136 | calibration 137 | { 138 | phi ~ maxent(Beta(), lower=0.6, upper=0.9) = 3/4; 139 | epsilon ~ maxent(Gamma(), lower=2, upper=20) = 11; 140 | rho_markup ~ maxent(Beta(), lower=0.7, upper=0.99) = 0.8; 141 | }; 142 | 143 | shocks 144 | { 145 | epsilon_markup[]; 146 | }; 147 | }; 148 | 149 | block GOVERNMENT 150 | { 151 | identities 152 | { 153 | 1 + i[] = (1 + i[ss]) * (pi[] / pi_bar) ^ phi_pi * (Y[] / Y[ss]) ^ phi_Y * interest_shock[]; 154 | log(interest_shock[]) = rho_i * log(interest_shock[-1]) + epsilon_i[]; 155 | 156 | i[-1] * B[-1] / pi[] = T[] + m[] - m[-1] / pi[] + B[] - B[-1] / pi[]; 157 | B[] = 0; 158 | }; 159 | 160 | shocks 161 | { 162 | epsilon_i[]; 163 | }; 164 | 165 | calibration 166 | { 167 | pi_bar = 1.0; 168 | rho_i ~ maxent(Beta(), lower=0.4, upper=0.99) = 0.5; 169 | phi_pi ~ maxent(Gamma(), lower=1.4, upper=2.0) = 1.5; 170 | phi_Y ~ maxent(Beta(), lower=0.01, upper=0.6) = 0.5; 171 | }; 172 | }; 173 | 174 | block EQULIBRIUM 175 | { 176 | identities 177 | { 178 | Y[] = C[]; 179 | }; 180 | }; 181 | -------------------------------------------------------------------------------- /GCN Files/sims_2024/nk_taylor_rule_capital.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | TC[], U[], Y_j[], T[], D[], q[]; 4 | }; 5 | 6 | 7 | block STEADY_STATE 8 | { 9 | definitions 10 | { 11 | K_to_N[ss] = (alpha * A[ss] * mc[ss] / r[ss]) ^ (1 / (1 - alpha)); 12 | }; 13 | 14 | identities 15 | { 16 | A[ss] = 1; 17 | interest_shock[ss] = 1; 18 | pi[ss] = pi_bar; 19 | pi_obj[ss] = pi_bar; 20 | 21 | epsilon_tv[ss] = epsilon; 22 | 23 | SDF[ss] = beta; 24 | 25 | r[ss] = 1 / beta - (1 - delta); 26 | i[ss] = pi[ss] / beta - 1; 27 | 28 | P_reset[ss] = ((1 - phi * pi[ss] ^ (epsilon - 1)) / (1 - phi)) ^ (1 / (1 - epsilon)); 29 | nu_p[ss] = (1 - phi) * P_reset[ss] ^ (-epsilon) / (1 - phi * pi[ss] ^ epsilon); 30 | 31 | mc[ss] = (epsilon - 1) / epsilon * P_reset[ss] * 32 | (1 - phi * beta * pi[ss] ^ epsilon) / (1 - phi * beta * pi[ss] ^ (epsilon - 1)); 33 | 34 | w[ss] = (1 - alpha) * A[ss] * mc[ss] * K_to_N[ss] ^ alpha; 35 | 36 | N[ss] = (w[ss] / theta / (A[ss] / nu_p[ss] * K_to_N[ss] ^ alpha - delta * K_to_N[ss]) ^ sigma) ^ (1 / (sigma + chi)); 37 | K[ss] = K_to_N[ss] * N[ss]; 38 | Y[ss] = A[ss] / nu_p[ss] * K[ss] ^ alpha * N[ss] ^ (1 - alpha); 39 | 40 | I[ss] = delta * K[ss]; 41 | C[ss] = Y[ss] - I[ss]; 42 | 43 | lambda[ss] = C[ss] ^ (-sigma); 44 | q[ss] = lambda[ss]; 45 | m[ss] = psi * ((1 + i[ss]) / i[ss]) * C[ss] ^ sigma; 46 | 47 | X_hat_1[ss] = mc[ss] * Y[ss] / (1 - phi * beta * pi[ss] ^ epsilon); 48 | X_hat_2[ss] = Y[ss] / (1 - beta * phi * pi[ss] ^ (epsilon - 1)); 49 | }; 50 | }; 51 | 52 | block HOUSEHOLD 53 | { 54 | 55 | definitions 56 | { 57 | u[] = C[] ^ (1 - sigma) / (1 - sigma) - theta * N[] ^ (1 + chi) / (1 + chi) + psi * log(m[]); 58 | }; 59 | 60 | objective 61 | { 62 | U[] = u[] + beta * E[][U[1]]; 63 | }; 64 | 65 | controls 66 | { 67 | C[], N[], m[], B[], K[], I[]; 68 | }; 69 | 70 | constraints 71 | { 72 | @exclude 73 | C[] + I[] + B[] + m[] - m[-1] / pi[] = w[] * N[] + r[] * K[-1] + (1 + i[-1]) * B[-1] / pi[] - T[] + D[]: lambda[]; 74 | K[] = (1 - delta) * K[-1] + I[] : q[]; 75 | }; 76 | 77 | identities 78 | { 79 | SDF[] = beta * lambda[] / lambda[-1]; 80 | }; 81 | 82 | calibration 83 | { 84 | beta ~ maxent(Beta(), lower=0.95, upper=0.99) = 0.99; 85 | delta ~ maxent(Beta(), lower=0.01, upper=0.05) = 0.035; 86 | sigma ~ maxent(Gamma(), lower=1.5, upper=5.0) = 3; 87 | theta ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 88 | chi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 89 | psi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 90 | }; 91 | 92 | }; 93 | 94 | block INTERMEDIATE_FIRM 95 | { 96 | objective 97 | { 98 | TC[] = -(w[] * N[] + r[] * K[-1]); 99 | }; 100 | 101 | controls 102 | { 103 | N[], K[-1]; 104 | }; 105 | 106 | constraints 107 | { 108 | Y_j[] = A[] * K[-1] ^ alpha * N[] ^ (1 - alpha) : mc[]; 109 | }; 110 | 111 | identities 112 | { 113 | D[] = Y_j[] + TC[]; 114 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 115 | }; 116 | 117 | shocks 118 | { 119 | epsilon_A[]; 120 | }; 121 | 122 | calibration 123 | { 124 | alpha ~ maxent(Beta(), lower=0.2, upper=0.5) = 0.33; 125 | rho_A ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 126 | }; 127 | 128 | }; 129 | 130 | block FINAL_GOODS 131 | { 132 | identities 133 | { 134 | # Reset price 135 | P_reset[] = epsilon_tv[] / (epsilon_tv[] - 1) * X_hat_1[] / X_hat_2[]; 136 | X_hat_1[] = mc[] * Y[] + phi * E[][SDF[1] * pi[1] ^ epsilon_tv[1] * X_hat_1[1]]; 137 | X_hat_2[] = Y[] + phi * E[][SDF[1] * pi[1] ^ (epsilon_tv[1] - 1) * X_hat_2[1]]; 138 | 139 | # Price index 140 | 1 = (1 - phi) * P_reset[] ^ (1 - epsilon_tv[]) + phi * pi[] ^ (epsilon_tv[] - 1); 141 | 142 | # Price distortion index 143 | nu_p[] = (1 - phi) * P_reset[] ^ (-epsilon_tv[]) + phi * pi[] ^ epsilon_tv[] * nu_p[-1]; 144 | 145 | # Aggregate production 146 | Y_j[] = nu_p[] * Y[]; 147 | 148 | # Time varying markup 149 | log(epsilon_tv[]) = (1 - rho_markup) * log(epsilon) + rho_markup * log(epsilon_tv[-1]) - epsilon_markup[]; 150 | }; 151 | 152 | calibration 153 | { 154 | phi ~ maxent(Beta(), lower=0.6, upper=0.9) = 3/4; 155 | epsilon ~ maxent(Gamma(), lower=2, upper=15, mass=0.99) = 11; 156 | rho_markup ~ maxent(Beta(), lower=0.7, upper=0.99) = 0.8; 157 | }; 158 | 159 | shocks 160 | { 161 | epsilon_markup[]; 162 | }; 163 | }; 164 | 165 | block GOVERNMENT 166 | { 167 | identities 168 | { 169 | # Central Bank 170 | i[] = (1 - rho_i) * i[ss] + 171 | rho_i * i[-1] + 172 | (1 - rho_i) * ( 173 | phi_pi * (log(pi[]) - log(pi_obj[])) + 174 | phi_Y * (log(Y[]) - log(Y[ss]))) + 175 | epsilon_i[]; 176 | 177 | log(pi_obj[]) = (1 - rho_pi_dot) * log(pi_bar) + 178 | rho_pi_dot * log(pi_obj[-1]) + epsilon_pi_obj[]; 179 | 180 | i[-1] * B[-1] / pi[] = T[] + m[] - m[-1] / pi[] + B[] - B[-1] / pi[]; 181 | B[] = 0; 182 | }; 183 | 184 | shocks 185 | { 186 | epsilon_i[], 187 | epsilon_pi_obj[]; 188 | }; 189 | 190 | calibration 191 | { 192 | pi_bar = 1.0; 193 | rho_i ~ maxent(Beta(), lower=0.4, upper=0.99) = 0.5; 194 | rho_pi_dot ~ maxent(Beta(), lower=0.5, upper=0.99) = 0.9; 195 | phi_pi ~ maxent(Gamma(), lower=1.4, upper=2.0) = 1.5; 196 | phi_Y ~ maxent(Beta(), lower=0.01, upper=0.6) = 0.5; 197 | }; 198 | }; 199 | 200 | block EQULIBRIUM 201 | { 202 | identities 203 | { 204 | Y[] = C[] + I[]; 205 | }; 206 | }; 207 | -------------------------------------------------------------------------------- /GCN Files/sims_2024/nk_taylor_rule_fully_linear.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | linear = True; 4 | }; 5 | 6 | block STEADY_STATE 7 | { 8 | identities 9 | { 10 | A[ss] = 0; 11 | interest_shock[ss] = 0; 12 | cost_push_shock[ss] = 0; 13 | 14 | pi[ss] = 0; 15 | i[ss] = 0; 16 | mc[ss] = 0; 17 | w[ss] = 0; 18 | N[ss] = 0; 19 | Y[ss] = 0; 20 | C[ss] = 0; 21 | }; 22 | }; 23 | 24 | block MODEL 25 | { 26 | identities 27 | { 28 | # IS curve 29 | Y[] = E[][Y[1]] - 1 / sigma * (i[] - E[][pi[1]]); 30 | 31 | # Labor supply 32 | chi * N[] = w[] - sigma * Y[]; 33 | 34 | # Marginal cost 35 | mc[] = w[] - A[]; 36 | 37 | # Production 38 | Y[] = A[] + N[]; 39 | 40 | # Phillips curve 41 | pi[] = (1 - phi) * (1 - phi * beta) / phi * mc[] + beta * E[][pi[1]] + cost_push_shock[]; 42 | 43 | # Taylor rule 44 | i[] = phi_pi * pi[] + phi_Y * Y[] + interest_shock[]; 45 | 46 | # Technology process 47 | A[] = rho_A * A[-1] + epsilon_A[]; 48 | 49 | # Cost push shock process 50 | cost_push_shock[] = rho_markup * cost_push_shock[-1] + epsilon_markup[]; 51 | 52 | # Interest shock process 53 | interest_shock[] = rho_i * interest_shock[-1] + epsilon_interest[]; 54 | }; 55 | 56 | shocks 57 | { 58 | epsilon_A[], epsilon_markup[], epsilon_interest[]; 59 | }; 60 | 61 | calibration 62 | { 63 | beta ~ maxent(Beta(), lower=0.95, upper=0.99) = 0.99; 64 | sigma ~ maxent(Gamma(), lower=1.5, upper=5.0) = 3; 65 | # theta ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 66 | chi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 67 | # psi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 68 | 69 | phi ~ maxent(Beta(), lower=0.6, upper=0.9) = 3/4; 70 | # epsilon ~ maxent(Gamma(), lower=2, upper=20) = 11; 71 | 72 | rho_markup ~ maxent(Beta(), lower=0.7, upper=0.99) = 0.8; 73 | rho_A ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 74 | rho_i ~ maxent(Beta(), lower=0.4, upper=0.99) = 0.5; 75 | 76 | phi_pi ~ maxent(Gamma(), lower=1.4, upper=2.0) = 1.5; 77 | phi_Y ~ maxent(Beta(), lower=0.01, upper=0.6) = 0.5; 78 | }; 79 | }; 80 | -------------------------------------------------------------------------------- /GCN Files/sims_2024/nk_taylor_rule_linearized.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | TC[], U[], Y_j[], T[], D[]; 4 | }; 5 | 6 | 7 | block STEADY_STATE 8 | { 9 | definitions 10 | { 11 | P_reset[ss] = ((1 - phi * pi[ss] ^ (epsilon - 1)) / (1 - phi)) ^ (1 / (1 - epsilon)); 12 | }; 13 | 14 | identities 15 | { 16 | A[ss] = 1; 17 | interest_shock[ss] = 1; 18 | cost_push_shock[ss] = 0; 19 | 20 | pi[ss] = pi_bar; 21 | 22 | SDF[ss] = beta; 23 | 24 | i[ss] = pi[ss] / beta - 1; 25 | 26 | mc[ss] = (epsilon - 1) / epsilon * P_reset[ss] * 27 | (1 - phi * beta * pi[ss] ^ epsilon) / (1 - phi * beta * pi[ss] ^ (epsilon - 1)); 28 | w[ss] = mc[ss] * A[ss]; 29 | 30 | N[ss] = (mc[ss] / theta) ^ (1 / (sigma + chi)); 31 | Y[ss] = N[ss]; 32 | C[ss] = Y[ss]; 33 | lambda[ss] = C[ss] ^ (-sigma); 34 | }; 35 | }; 36 | 37 | block HOUSEHOLD 38 | { 39 | 40 | definitions 41 | { 42 | u[] = C[] ^ (1 - sigma) / (1 - sigma) - theta * N[] ^ (1 + chi) / (1 + chi); 43 | }; 44 | 45 | objective 46 | { 47 | U[] = u[] + beta * E[][U[1]]; 48 | }; 49 | 50 | controls 51 | { 52 | C[], N[], B[]; 53 | }; 54 | 55 | constraints 56 | { 57 | @exclude 58 | C[] + B[] = w[] * N[] + (1 + i[-1]) * B[-1] / pi[] - T[] + D[]: lambda[]; 59 | }; 60 | 61 | identities 62 | { 63 | SDF[] = beta * lambda[] / lambda[-1]; 64 | }; 65 | 66 | calibration 67 | { 68 | beta ~ maxent(Beta(), lower=0.95, upper=0.99) = 0.99; 69 | sigma ~ maxent(Gamma(), lower=1.5, upper=5.0) = 3; 70 | theta ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 71 | chi ~ maxent(Gamma(), lower=0.8, upper=3.0) = 1.0; 72 | }; 73 | 74 | }; 75 | 76 | block INTERMEDIATE_FIRM 77 | { 78 | objective 79 | { 80 | TC[] = -(w[] * N[]); 81 | }; 82 | 83 | controls 84 | { 85 | N[]; 86 | }; 87 | 88 | constraints 89 | { 90 | Y_j[] = A[] * N[] : mc[]; 91 | }; 92 | 93 | identities 94 | { 95 | D[] = Y_j[] + TC[]; 96 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 97 | }; 98 | 99 | shocks 100 | { 101 | epsilon_A[]; 102 | }; 103 | 104 | calibration 105 | { 106 | rho_A ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 107 | }; 108 | 109 | }; 110 | 111 | block FINAL_GOODS 112 | { 113 | identities 114 | { 115 | # Log linear phillips curve 116 | log(pi[] / pi_bar) = (1 - phi) * (1 - phi * beta) / phi * log(mc[] / mc[ss]) + beta * E[][log(pi[1] / pi_bar)] + cost_push_shock[]; 117 | 118 | # Time varying markup 119 | cost_push_shock[] = rho_p * cost_push_shock[-1] + epsilon_p[]; 120 | 121 | # Aggregate production 122 | Y_j[] = Y[]; 123 | 124 | }; 125 | 126 | calibration 127 | { 128 | phi ~ maxent(Beta(), lower=0.6, upper=0.9) = 3/4; 129 | epsilon ~ maxent(Gamma(), lower=2, upper=20) = 11; 130 | rho_p ~ maxent(Beta(), lower=0.7, upper=0.99) = 0.8; 131 | }; 132 | 133 | shocks 134 | { 135 | epsilon_p[]; 136 | }; 137 | }; 138 | 139 | block GOVERNMENT 140 | { 141 | identities 142 | { 143 | 1 + i[] = (1 + i[ss]) * (pi[] / pi_bar) ^ phi_pi * (Y[] / Y[ss]) ^ phi_Y * interest_shock[]; 144 | log(interest_shock[]) = rho_i * log(interest_shock[-1]) + epsilon_i[]; 145 | 146 | i[-1] * B[-1] / pi[] = T[] + B[] - B[-1] / pi[]; 147 | B[] = 0; 148 | }; 149 | 150 | shocks 151 | { 152 | epsilon_i[]; 153 | }; 154 | 155 | calibration 156 | { 157 | pi_bar = 1.0; 158 | rho_i ~ maxent(Beta(), lower=0.4, upper=0.99) = 0.5; 159 | phi_pi ~ maxent(Gamma(), lower=1.4, upper=2.0) = 1.5; 160 | phi_Y ~ maxent(Beta(), lower=0.01, upper=0.6) = 0.5; 161 | }; 162 | }; 163 | 164 | block EQULIBRIUM 165 | { 166 | identities 167 | { 168 | Y[] = C[]; 169 | }; 170 | }; 171 | -------------------------------------------------------------------------------- /GCN Files/skilled_unskilled_rbc.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | identities 4 | { 5 | A[ss] = 1.0; 6 | Div[ss] = 0.0; 7 | r_u[ss] = 1 / beta_u - (1 - delta_u); 8 | r_s[ss] = 1 / beta_s - (1 - delta_s); 9 | }; 10 | }; 11 | 12 | block SKILLED_HOUSEHOLD 13 | { 14 | definitions 15 | { 16 | u_s[] = log(C_s[]) - Theta_s * L_s[]; 17 | }; 18 | 19 | objective 20 | { 21 | U_s[] = u_s[] + beta_s * E[][U_s[1]]; 22 | }; 23 | 24 | controls 25 | { 26 | C_s[], L_s[], K_s[], I_s[]; 27 | }; 28 | 29 | constraints 30 | { 31 | C_s[] + I_s[] = w_s[] * L_s[] + r_s[] * K_s[-1] + s * Div[]: lambda_s[]; 32 | K_s[] = (1 - delta_s) * K_s[-1] + I_s[]; 33 | }; 34 | 35 | calibration 36 | { 37 | beta_s = 0.99; 38 | delta_s = 0.035; 39 | Theta_s = 1; 40 | s = 0.5; # Share of dividend that the skilled household gets (could be alpha_L ?) 41 | }; 42 | }; 43 | 44 | block UNSKILLED_HOUSEHOLD 45 | { 46 | definitions 47 | { 48 | u_u[] = log(C_u[]) - Theta_u * L_u[]; 49 | }; 50 | 51 | objective 52 | { 53 | U_u[] = u_u[] + beta_u * E[][U_u[1]]; 54 | }; 55 | 56 | controls 57 | { 58 | C_u[], L_u[], K_u[], I_u[]; 59 | }; 60 | 61 | constraints 62 | { 63 | C_u[] + I_u[] = w_u[] * L_u[] + r_u[] * K_u[-1] + (1 - s) * Div[]: lambda_u[]; 64 | K_u[] = (1 - delta_u) * K_u[-1] + I_u[]; 65 | }; 66 | 67 | calibration 68 | { 69 | beta_u = 0.99; 70 | delta_u = 0.035; 71 | Theta_u = 1; 72 | }; 73 | }; 74 | 75 | 76 | block FIRM 77 | { 78 | objective 79 | { 80 | TC[] = -(r_u[] * K_u[] + r_s[] * K_s[] + w_u[] * L_u[] + w_s[] * L_s[]); 81 | }; 82 | 83 | controls 84 | { 85 | K_u[-1], K_s[-1], L_u[], L_s[], K[], L[]; 86 | }; 87 | 88 | constraints 89 | { 90 | # Bundle labor -- skilled/unskilled are imperfect substitutes 91 | L[] = (alpha_L ^ (1 / psi_L) * L_u[] ^ ((psi_L - 1) / psi_L) + 92 | (1 - alpha_L) ^ (1 / psi_L) * L_s[] ^ ((psi_L - 1) / psi_L)) ^ 93 | (psi_L / (psi_L - 1)); 94 | 95 | # Bundle capital -- perfect substitutes 96 | K[] = K_u[-1] ^ alpha_K * K_s[-1] ^ (1 - alpha_K); 97 | 98 | # Production function 99 | Y[] = A[] * K[] ^ alpha * L[] ^ (1 - alpha) : P[]; 100 | }; 101 | 102 | identities 103 | { 104 | # Perfect competition 105 | P[] = 1; 106 | Div[] = Y[] * P[] + TC[]; 107 | }; 108 | 109 | calibration 110 | { 111 | alpha_L = 0.5; # share of unskilled labor in economy 112 | alpha_K = 0.5; # share of capital stock owned by unskilled household 113 | psi_L = 3.0; # Elasticity of substitution btwn skilled & unskilled, psi_L -> oo implies perfect substitutes 114 | alpha = 0.66; # Share of capital in production 115 | }; 116 | }; 117 | 118 | block TECHNOLOGY 119 | { 120 | identities 121 | { 122 | log(A[]) = rho * log(A[-1]) + epsilon_A[]; 123 | }; 124 | 125 | shocks 126 | { 127 | epsilon_A[]; 128 | }; 129 | 130 | calibration 131 | { 132 | rho = 0.95; 133 | }; 134 | }; 135 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | 4 | coverage: 5 | precision: 2 6 | round: down 7 | range: "70...100" 8 | status: 9 | project: 10 | default: 11 | # basic 12 | target: auto 13 | threshold: 1% 14 | base: auto 15 | patch: 16 | default: 17 | # basic 18 | target: 50% 19 | threshold: 1% 20 | base: auto 21 | 22 | ignore: 23 | - "gEconpy/tests/*" 24 | 25 | comment: 26 | layout: "reach, diff, flags, files" 27 | behavior: default 28 | require_changes: false # if true: only post the comment if coverage changes 29 | require_base: no # [yes :: must have a base report to post] 30 | require_head: yes # [yes :: must have a head report to post] 31 | branches: null # branch names that can post comment 32 | -------------------------------------------------------------------------------- /conda_envs/environment.yml: -------------------------------------------------------------------------------- 1 | name: geconpy 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # Core dependencies 6 | - python=3.12 7 | - pymc 8 | - pytensor 9 | - joblib 10 | - matplotlib 11 | - numba 12 | - numpy 13 | - pandas 14 | - pyparsing 15 | - scipy 16 | - setuptools 17 | - statsmodels 18 | - preliz 19 | - sympy<1.13 20 | - pymc-extras 21 | - better-optimize 22 | - preliz 23 | - ipython 24 | - nutpie 25 | - sympytensor 26 | - pymc-extras 27 | 28 | - pip: 29 | - flowjax 30 | -------------------------------------------------------------------------------- /conda_envs/environment_dev.yml: -------------------------------------------------------------------------------- 1 | name: geconpy-dev 2 | channels: 3 | - conda-forge 4 | - nvidia 5 | - nodefaults 6 | 7 | dependencies: 8 | # Core dependencies 9 | - python=3.12 10 | - pymc 11 | - pytensor 12 | - joblib 13 | - matplotlib 14 | - numba 15 | - numpy 16 | - pandas 17 | - pyparsing 18 | - preliz 19 | - scipy 20 | - setuptools 21 | - statsmodels 22 | - sympy<1.13 23 | - preliz 24 | - pip 25 | - ipython 26 | - notebook<7 27 | - nutpie 28 | - sympytensor 29 | - pymc-extras 30 | 31 | # JAX, optional for now 32 | - jax 33 | # - jaxlib=*=*cuda* 34 | 35 | # For building docs 36 | - ipython 37 | - jupyter-sphinx 38 | - myst-nb 39 | - numpydoc 40 | - pre-commit 41 | - sphinx>=5 42 | - sphinx-copybutton 43 | - sphinx-design 44 | - sphinx-notfound-page 45 | - sphinx-sitemap 46 | - sphinx-codeautolink 47 | - sphinxcontrib-bibtex 48 | - pydata-sphinx-theme 49 | - watermark 50 | 51 | # developer tools 52 | - pre-commit 53 | - pytest 54 | - pytest-env 55 | - pytest-cov 56 | - pandas-datareader 57 | 58 | - pip: 59 | - numdifftools 60 | - -e ../. 61 | -------------------------------------------------------------------------------- /conda_envs/environment_docs.yml: -------------------------------------------------------------------------------- 1 | name: geconpy-docs 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # Core dependencies 6 | - python=3.12 7 | - pip 8 | - pymc 9 | - pytensor 10 | - joblib 11 | - matplotlib 12 | - numba 13 | - numpy 14 | - pandas 15 | - pyparsing 16 | - scipy 17 | - setuptools 18 | - statsmodels 19 | - preliz 20 | - sympy<1.13 21 | - pymc-extras 22 | - better-optimize 23 | - jax 24 | - nutpie 25 | - sympytensor 26 | 27 | # Extra dependencies for docs build 28 | - ipython 29 | - jupyter-sphinx 30 | - myst-nb 31 | - numpydoc 32 | - pre-commit 33 | - sphinx>=5 34 | - sphinx-copybutton 35 | - sphinx-design 36 | - sphinx-notfound-page 37 | - sphinx-sitemap 38 | - sphinx-codeautolink 39 | - sphinxcontrib-bibtex 40 | - pydata-sphinx-theme 41 | - watermark 42 | -------------------------------------------------------------------------------- /conda_envs/geconpy_test.yml: -------------------------------------------------------------------------------- 1 | name: gEconpy 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # Base dependencies 6 | - numpy 7 | - numba 8 | - scipy 9 | - sympy<1.13 10 | - pyparsing 11 | - pandas 12 | - xarray 13 | - matplotlib 14 | - joblib 15 | - arviz 16 | - statsmodels 17 | - pymc 18 | - pytensor 19 | - preliz 20 | - ipython 21 | 22 | # Testing dependencies 23 | - pre-commit 24 | - pytest-cov>=2.5 25 | - pytest>=3.0 26 | - pytest-env 27 | 28 | - pip 29 | - better-optimize 30 | - nutpie 31 | - sympytensor 32 | - pymc-extras 33 | 34 | - pip: 35 | - numdifftools 36 | - jax 37 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/scripts/rerun_examples.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script/module may be used to re-run, commit & push notebooks 3 | from the CLI or from another Python script (via `import rerun`). 4 | 5 | Run `python rerun.py -h` to show the CLI help. 6 | 7 | The example below does the following: 8 | 1. Re-runs the BEST notebook 9 | 2. Commits changes to a branch "rerun-best" 10 | 3. Push that branch to a remote named "mine" 11 | Assuming you did something like: `git add remote mine https://github.com/yourgithubusername/pymc-examples` 12 | 13 | ``` 14 | python scripts/rerun.py --fp_notebook=examples/case_studies/BEST.ipynb --commit_to=rerun-best --push_to=mine 15 | ``` 16 | """ 17 | 18 | import argparse 19 | import logging 20 | from pathlib import Path 21 | import subprocess 22 | 23 | 24 | logging.basicConfig(level=logging.INFO) 25 | _log = logging.getLogger(__file__) 26 | DP_REPO = Path(__file__).absolute().parent.parent / "source" / "examples" 27 | 28 | 29 | def run_precommit(fp: Path, attempts: int = 2): 30 | try: 31 | for a in range(attempts): 32 | _log.info("⏳ Running pre-commit attempt %i on %s", a, fp) 33 | try: 34 | subprocess.check_call(["pre-commit", "run", "--files", str(fp)]) 35 | break 36 | except subprocess.CalledProcessError: 37 | if a == attempts - 1: 38 | raise 39 | return True 40 | except Exception as ex: 41 | _log.exception("❌ Failed to run pre-commit.", exc_info=ex) 42 | return False 43 | 44 | 45 | def execute_notebook(fp: Path) -> bool: 46 | try: 47 | _log.info("⏳ Executing notebook %s", fp) 48 | subprocess.check_call( 49 | [ 50 | "jupyter", 51 | "nbconvert", 52 | "--ExecutePreprocessor.kernel_name=python3", 53 | "--ExecutePreprocessor.timeout=14000", 54 | "--execute", 55 | "--inplace", 56 | str(fp), 57 | ] 58 | ) 59 | _log.info("✔ Notebook executed successfully.") 60 | return True 61 | except subprocess.CalledProcessError as ex: 62 | _log.exception("❌ Failed to commit.", exc_info=ex) 63 | return False 64 | 65 | 66 | def commit(fp: Path, branch: str) -> bool: 67 | try: 68 | _log.info("Switching to branch %s", branch) 69 | if branch not in subprocess.check_output(["git", "branch"]).decode("ascii"): 70 | subprocess.check_call(["git", "checkout", "-b", branch]) 71 | else: 72 | subprocess.check_call(["git", "checkout", branch]) 73 | 74 | _log.info("⏳ Committing changes in %s to %s", fp, branch) 75 | subprocess.check_call(["git", "stage", str(fp)]) 76 | subprocess.check_call(["git", "commit", "-m", f"Re-run {fp.name} notebook"]) 77 | _log.info("✔ Changes in %s were committed to branch %s.", fp, branch) 78 | return True 79 | except subprocess.CalledProcessError as ex: 80 | _log.exception("❌ Failed to commit.", exc_info=ex) 81 | return False 82 | 83 | 84 | def push(branch, remote: str) -> bool: 85 | try: 86 | _log.info("⏳ Pushing %s to %s", branch, remote) 87 | subprocess.check_call(["git", "push", "-u", remote, f"{branch}:{branch}"]) 88 | _log.info("✔ Pushed %s to %s/%s.", branch, remote, branch) 89 | return True 90 | except subprocess.CalledProcessError as ex: 91 | _log.exception("❌ Failed push.", exc_info=ex) 92 | return False 93 | 94 | 95 | def get_args(): 96 | parser = argparse.ArgumentParser() 97 | parser.add_argument( 98 | "--fp_notebook", 99 | type=str, 100 | help=f"Absolute or relative path to a Jupyter notebook in {str(DP_REPO)}.", 101 | required=True, 102 | ) 103 | parser.add_argument( 104 | "--commit_to", 105 | type=str, 106 | help="Name of a git branch to commit to on success.", 107 | required=False, 108 | ) 109 | parser.add_argument( 110 | "--push_to", 111 | type=str, 112 | help="Name of a git remote to push to on success.", 113 | required=False, 114 | ) 115 | return parser.parse_args() 116 | 117 | 118 | if __name__ == "__main__": 119 | args = get_args() 120 | 121 | fp = DP_REPO / Path(args.fp_notebook) 122 | if not fp.exists(): 123 | raise FileNotFoundError(f"Notebook file {fp} does not exist.") 124 | 125 | success = True 126 | success = success and run_precommit(fp) 127 | success = success and execute_notebook(fp) 128 | if args.commit_to: 129 | success = success and run_precommit(fp) 130 | success = success and commit(fp, args.commit_to) 131 | if success and args.push_to: 132 | success = success and push(args.commit_to, args.push_to) 133 | 134 | if success: 135 | _log.info("✔ All steps succeeded.") 136 | else: 137 | _log.error("❌ Manual investigation needed.") 138 | -------------------------------------------------------------------------------- /docs/source/_templates/autosummary/class.rst: -------------------------------------------------------------------------------- 1 | {{ fullname | escape | underline}} 2 | 3 | .. currentmodule:: {{ module }} 4 | 5 | .. autoclass:: {{ objname }} 6 | 7 | {% block methods %} 8 | {% if methods %} 9 | 10 | .. rubric:: Methods 11 | 12 | .. autosummary:: 13 | :toctree: classmethods 14 | 15 | {% for item in methods %} 16 | {%- if item not in inherited_members %} 17 | {{ objname }}.{{ item }} 18 | {% endif %} 19 | {%- endfor %} 20 | {% endif %} 21 | {% endblock %} 22 | 23 | {% block attributes %} 24 | {% if attributes %} 25 | .. rubric:: Attributes 26 | 27 | .. autosummary:: 28 | {% for item in attributes %} 29 | {%- if item not in inherited_members %} 30 | ~{{ name }}.{{ item }} 31 | {% endif %} 32 | {%- endfor %} 33 | {% endif %} 34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /docs/source/_templates/nb-badges.html: -------------------------------------------------------------------------------- 1 | {% if pagename in ablog %} 2 | 3 | 4 | {% set gh_basepath = github_user + '/' + github_repo + '/blob/' + github_version + '/' %} 5 | {% set encoded_base = github_user + '%252F' + github_repo %} 6 | {% set gh_binder = github_user + '/' + github_repo + '/' + github_version %} 7 | {% set doc_path_aux = doc_path | trim('/') %} 8 | {% set file_path = doc_path_aux + '/' + pagename + ".ipynb" %} 9 | {% set encoded_path = file_path | replace("/", "%252F") %} 10 | 11 | 12 |
13 |

14 | 15 | View On GitHub 16 | 17 | 18 | Open In Binder 19 | 20 | 21 | Open In Colab 22 |

23 |
24 | {% endif %} 25 | -------------------------------------------------------------------------------- /docs/source/_templates/postcard.html: -------------------------------------------------------------------------------- 1 | {% if pagename in ablog %} 2 | {% set post = ablog[pagename] %} 3 | 4 | {% if post.tags %} 5 |
6 | 7 | {% if post.tags|length > 1 %} 8 | {% else %} 9 | {% endif %} 10 | 11 | {% for coll in post.tags %} {% if coll|length %} 12 | {{ coll }}{% if loop.index < 13 | post.tags|length %}{% endif %} {% else %}{{ coll }}{% if loop.index < 14 | post.tags|length %}{% endif %}{% endif %} {% endfor %} 15 |
16 | {% endif %} 17 | {% endif %} 18 | -------------------------------------------------------------------------------- /docs/source/_templates/postcard_categories.html: -------------------------------------------------------------------------------- 1 | {%- macro pathtocategory(category) -%} 2 | {% set path = "blog/category/" + category %} 3 | {{ pathto(path) }} 4 | {%- endmacro -%} 5 | 6 | {%- macro setcolorclass(active) -%} 7 | {% if active %} 8 | {{ "sd-text-success" }} 9 | {% else %} 10 | {{ "sd-text-muted" }} 11 | {% endif %} 12 | {%- endmacro -%} 13 | 14 | {%- macro category_item(name, active) -%} 15 | 16 | {{ name }} 17 | 18 | {%- endmacro -%} 19 | 20 | 21 | 22 | {% set post = ablog[pagename] %} 23 | 24 | 25 |

26 | {{ gettext('Categories') }} 27 |

28 |
29 | 30 | {% set i_bool = "intermediate" in post.category|map('string') %} 31 | {% set b_bool = "beginner" in post.category|map('string') %} 32 | {% set a_bool = "advanced" in post.category|map('string') %} 33 |
34 |
35 |
36 | {{ category_item("beginner", b_bool) }} 37 |
38 |
39 | {{ category_item("intermediate", i_bool) }} 40 |
41 |
42 | {{ category_item("advanced", a_bool) }} 43 |
44 |
45 |
46 |
47 | -------------------------------------------------------------------------------- /docs/source/_templates/rendered_citations.html: -------------------------------------------------------------------------------- 1 | {%- macro pathtocategory(category) -%} 2 | {% set path = "blog/category/" + category %} 3 | {{ pathto(path) }} 4 | {%- endmacro -%} 5 | 6 | {%- macro setcolorclass(active) -%} 7 | {% if active %} 8 | {{ "sd-text-success" }} 9 | {% else %} 10 | {{ "sd-text-muted" }} 11 | {% endif %} 12 | {%- endmacro -%} 13 | 14 | {%- macro category_item(name, active) -%} 15 | 16 | {{ name }} 17 | 18 | {%- endmacro -%} 19 | 20 | 21 | 22 | {% set post = ablog[pagename] %} 23 | 24 | 25 |

26 | {{ gettext('Categories') }} 27 |

28 |
29 | 30 | {% set i_bool = "intermediate" in post.category|map('string') %} 31 | {% set b_bool = "beginner" in post.category|map('string') %} 32 | {% set a_bool = "advanced" in post.category|map('string') %} 33 |
34 |
35 |
36 | {{ category_item("beginner", b_bool) }} 37 |
38 |
39 | {{ category_item("intermediate", i_bool) }} 40 |
41 |
42 | {{ category_item("advanced", a_bool) }} 43 |
44 |
45 |
46 |
47 | -------------------------------------------------------------------------------- /docs/source/api.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | API 4 | === 5 | 6 | .. toctree:: 7 | :maxdepth: 1 8 | :titlesonly: 9 | 10 | api/classes 11 | api/dynare_convert 12 | api/exceptions 13 | api/model 14 | api/numbaf 15 | api/parser 16 | api/plotting 17 | api/solvers 18 | api/utilities 19 | -------------------------------------------------------------------------------- /docs/source/api/classes.rst: -------------------------------------------------------------------------------- 1 | .. _api_classes: 2 | 3 | ******** 4 | Classes 5 | ******** 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | classes/containers 11 | classes/time_aware_symbol 12 | -------------------------------------------------------------------------------- /docs/source/api/classes/containers.rst: -------------------------------------------------------------------------------- 1 | ********** 2 | Containers 3 | ********** 4 | 5 | .. currentmodule:: gEconpy.classes.containers 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | safe_string_to_sympy 11 | symbol_to_string 12 | string_keys_to_sympy 13 | sympy_keys_to_strings 14 | sympy_number_values_to_floats 15 | float_values_to_sympy_float 16 | sort_dictionary 17 | 18 | SymbolDictionary 19 | -------------------------------------------------------------------------------- /docs/source/api/classes/time_aware_symbol.rst: -------------------------------------------------------------------------------- 1 | ***************** 2 | Time Aware Symbol 3 | ***************** 4 | 5 | .. currentmodule:: gEconpy.classes.time_aware_symbol 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | TimeAwareSymbol 11 | -------------------------------------------------------------------------------- /docs/source/api/dynare_convert.rst: -------------------------------------------------------------------------------- 1 | .. _api_dynare_convet: 2 | 3 | ********************* 4 | Write Model to Dynare 5 | ********************* 6 | 7 | .. automodule:: gEconpy.dynare_convert 8 | 9 | .. autosummary:: 10 | :toctree: generated/ 11 | -------------------------------------------------------------------------------- /docs/source/api/exceptions.rst: -------------------------------------------------------------------------------- 1 | .. _api_exceptions: 2 | 3 | ********** 4 | Exceptions 5 | ********** 6 | 7 | 8 | .. automodule:: gEconpy.exceptions 9 | 10 | .. autosummary:: 11 | :toctree: generated/ 12 | 13 | GCNSyntaxError 14 | DistributionParsingError 15 | MissingParameterValueException 16 | InvalidComponentNameException 17 | BlockNotInitializedException 18 | DynamicCalibratingEquationException 19 | OptimizationProblemNotDefinedException 20 | MultipleObjectiveFunctionsException 21 | ControlVariableNotFoundException 22 | ModelUnknownParameterError 23 | PerturbationSolutionNotFoundException 24 | SteadyStateNotFoundError 25 | MultipleSteadyStateBlocksException 26 | GensysFailedException 27 | VariableNotFoundException 28 | InvalidDistributionException 29 | RepeatedParameterException 30 | DistributionParameterNotFoundException 31 | MultipleParameterDefinitionException 32 | UnusedParameterError 33 | InvalidParameterException 34 | InvalidMeanException 35 | DistributionOverDefinedException 36 | OrphanParameterError 37 | ExtraParameterError 38 | ExtraParameterWarning 39 | DuplicateParameterError 40 | -------------------------------------------------------------------------------- /docs/source/api/model.rst: -------------------------------------------------------------------------------- 1 | .. _api_model: 2 | 3 | ***** 4 | Model 5 | ***** 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | model/block 11 | model/build 12 | model/compile 13 | model/model 14 | model/parameters 15 | model/perturbation 16 | model/simplification 17 | model/statespace 18 | model/steady_state 19 | -------------------------------------------------------------------------------- /docs/source/api/model/block.rst: -------------------------------------------------------------------------------- 1 | ***** 2 | Block 3 | ***** 4 | 5 | .. automodule:: gEconpy.model.block 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | Block 11 | -------------------------------------------------------------------------------- /docs/source/api/model/build.rst: -------------------------------------------------------------------------------- 1 | ***** 2 | Build 3 | ***** 4 | 5 | .. automodule:: gEconpy.model.build 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | model_from_gcn 11 | statespace_from_gcn 12 | 13 | split_out_hyper_params 14 | -------------------------------------------------------------------------------- /docs/source/api/model/compile.rst: -------------------------------------------------------------------------------- 1 | ******* 2 | Compile 3 | ******* 4 | 5 | .. automodule:: gEconpy.model.compile 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | compile_function 11 | compile_to_numpy 12 | compile_to_numba 13 | compile_to_pytensor_function 14 | 15 | 16 | ***************** 17 | Function Wrappers 18 | ***************** 19 | 20 | .. automodule:: gEconpy.model.compile 21 | 22 | .. autosummary:: 23 | :toctree: generated/ 24 | 25 | dictionary_return_wrapper 26 | stack_return_wrapper 27 | pop_return_wrapper 28 | array_return_wrapper 29 | -------------------------------------------------------------------------------- /docs/source/api/model/model.rst: -------------------------------------------------------------------------------- 1 | ***** 2 | Model 3 | ***** 4 | 5 | .. currentmodule:: gEconpy.model.model 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | Model 11 | 12 | 13 | ******************* 14 | Working with Models 15 | ******************* 16 | .. currentmodule:: gEconpy.model.model 17 | 18 | .. autosummary:: 19 | :toctree: generated/ 20 | 21 | stationary_covariance_matrix 22 | check_bk_condition 23 | autocovariance_matrix 24 | autocorrelation_matrix 25 | summarize_perturbation_solution 26 | impulse_response_function 27 | simulate 28 | matrix_to_dataframe 29 | check_steady_state 30 | -------------------------------------------------------------------------------- /docs/source/api/model/parameters.rst: -------------------------------------------------------------------------------- 1 | ********** 2 | Parameters 3 | ********** 4 | 5 | .. automodule:: gEconpy.model.parameters 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | compile_param_dict_func 11 | -------------------------------------------------------------------------------- /docs/source/api/model/perturbation.rst: -------------------------------------------------------------------------------- 1 | ************ 2 | Perturbation 3 | ************ 4 | 5 | .. automodule:: gEconpy.model.perturbation 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | linearize_model 11 | compile_linearized_system 12 | check_bk_condition 13 | 14 | 15 | **************** 16 | Helper Functions 17 | **************** 18 | 19 | .. automodule:: gEconpy.model.perturbation 20 | 21 | .. autosummary:: 22 | :toctree: generated/ 23 | 24 | make_not_loglin_flags 25 | override_dummy_wrapper 26 | make_all_variable_time_combinations 27 | statespace_to_gEcon_representation 28 | check_perturbation_solution 29 | 30 | ************ 31 | Pytensor Ops 32 | ************ 33 | 34 | .. automodule:: gEconpy.model.perturbation 35 | 36 | .. autosummary:: 37 | :toctree: generated/ 38 | 39 | check_bk_condition_pt 40 | -------------------------------------------------------------------------------- /docs/source/api/model/simplification.rst: -------------------------------------------------------------------------------- 1 | ************** 2 | Simplification 3 | ************** 4 | 5 | .. automodule:: gEconpy.model.simplification 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | simplify_tryreduce 11 | simplify_constants 12 | reduce_variable_list 13 | -------------------------------------------------------------------------------- /docs/source/api/model/statespace.rst: -------------------------------------------------------------------------------- 1 | *********** 2 | State Space 3 | *********** 4 | 5 | .. currentmodule:: gEconpy.model.statespace 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | DSGEStateSpace 11 | data_from_prior 12 | -------------------------------------------------------------------------------- /docs/source/api/model/steady_state.rst: -------------------------------------------------------------------------------- 1 | ************ 2 | Steady State 3 | ************ 4 | 5 | .. automodule:: gEconpy.model.steady_state 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | steady_state_error_function 11 | compile_ss_resid_and_sq_err 12 | compile_known_ss 13 | compile_model_ss_functions 14 | print_steady_state 15 | -------------------------------------------------------------------------------- /docs/source/api/numbaf.rst: -------------------------------------------------------------------------------- 1 | .. _api_numbaf: 2 | 3 | *************** 4 | Numba Functions 5 | *************** 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | 11 | numbaf/LAPACK 12 | numbaf/overloads 13 | numbaf/utilities 14 | -------------------------------------------------------------------------------- /docs/source/api/numbaf/LAPACK.rst: -------------------------------------------------------------------------------- 1 | **************** 2 | LAPACK Functions 3 | **************** 4 | 5 | .. automodule:: gEconpy.numbaf.LAPACK 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | _LAPACK 11 | -------------------------------------------------------------------------------- /docs/source/api/numbaf/overloads.rst: -------------------------------------------------------------------------------- 1 | ************************ 2 | Numba Function Overloads 3 | ************************ 4 | 5 | .. automodule:: gEconpy.numbaf.overloads 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | -------------------------------------------------------------------------------- /docs/source/api/numbaf/utilities.rst: -------------------------------------------------------------------------------- 1 | *************** 2 | Numba Utilities 3 | *************** 4 | 5 | .. automodule:: gEconpy.numbaf.utilities 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | -------------------------------------------------------------------------------- /docs/source/api/parser.rst: -------------------------------------------------------------------------------- 1 | .. _api_parser: 2 | 3 | ********** 4 | GCN Parser 5 | ********** 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | parser/file_loaders 11 | parser/gEcon_parser 12 | parser/parse_distributions 13 | parser/parse_equations 14 | parser/parse_plaintext 15 | parser/validation 16 | -------------------------------------------------------------------------------- /docs/source/api/parser/file_loaders.rst: -------------------------------------------------------------------------------- 1 | ************ 2 | File Loaders 3 | ************ 4 | 5 | .. automodule:: gEconpy.parser.file_loaders 6 | 7 | .. autosummary:: 8 | :toctree: generated 9 | -------------------------------------------------------------------------------- /docs/source/api/parser/gEcon_parser.rst: -------------------------------------------------------------------------------- 1 | ************ 2 | gEcon Parser 3 | ************ 4 | 5 | .. automodule:: gEconpy.parser.gEcon_parser 6 | 7 | .. autosummary:: 8 | :toctree: generated 9 | -------------------------------------------------------------------------------- /docs/source/api/parser/parse_distributions.rst: -------------------------------------------------------------------------------- 1 | ******************* 2 | Parse Distributions 3 | ******************* 4 | 5 | .. automodule:: gEconpy.parser.parse_distributions 6 | 7 | .. autosummary:: 8 | :toctree: generated 9 | -------------------------------------------------------------------------------- /docs/source/api/parser/parse_equations.rst: -------------------------------------------------------------------------------- 1 | *************** 2 | Parse Equations 3 | *************** 4 | 5 | .. automodule:: gEconpy.parser.parse_equations 6 | 7 | .. autosummary:: 8 | :toctree: generated 9 | -------------------------------------------------------------------------------- /docs/source/api/parser/parse_plaintext.rst: -------------------------------------------------------------------------------- 1 | *************** 2 | Parse Plaintext 3 | *************** 4 | 5 | .. automodule:: gEconpy.parser.parse_plaintext 6 | 7 | .. autosummary:: 8 | :toctree: generated 9 | -------------------------------------------------------------------------------- /docs/source/api/parser/validation.rst: -------------------------------------------------------------------------------- 1 | ***************** 2 | Parser Validation 3 | ***************** 4 | 5 | .. automodule:: gEconpy.parser.validation 6 | 7 | .. autosummary:: 8 | :toctree: generated 9 | -------------------------------------------------------------------------------- /docs/source/api/plotting.rst: -------------------------------------------------------------------------------- 1 | .. _api_plotting: 2 | 3 | ******** 4 | Plotting 5 | ******** 6 | 7 | .. automodule:: gEconpy.plotting 8 | 9 | .. autosummary:: 10 | :toctree: generated/ 11 | 12 | plot_simulation 13 | plot_irf 14 | plot_prior_solvability 15 | plot_eigenvalues 16 | plot_covariance_matrix 17 | plot_heatmap 18 | plot_acf 19 | plot_corner 20 | plot_kalman_filter 21 | -------------------------------------------------------------------------------- /docs/source/api/solvers.rst: -------------------------------------------------------------------------------- 1 | .. _api_solvers: 2 | 3 | ******* 4 | Solvers 5 | ******* 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | solvers/cycle_reduction 11 | solvers/gensys 12 | solvers/shared 13 | -------------------------------------------------------------------------------- /docs/source/api/solvers/cycle_reduction.rst: -------------------------------------------------------------------------------- 1 | *************** 2 | Cycle Reduction 3 | *************** 4 | 5 | .. automodule:: gEconpy.solvers.cycle_reduction 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | solve_policy_function_with_cycle_reduction 11 | 12 | cycle_reduction_pt 13 | scan_cycle_reduction 14 | -------------------------------------------------------------------------------- /docs/source/api/solvers/gensys.rst: -------------------------------------------------------------------------------- 1 | ****** 2 | Gensys 3 | ****** 4 | 5 | .. automodule:: gEconpy.solvers.gensys 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | qzdiv 11 | qzswitch 12 | gensys 13 | interpret_gensys_output 14 | solve_policy_function_with_gensys 15 | gensys_pt 16 | -------------------------------------------------------------------------------- /docs/source/api/solvers/shared.rst: -------------------------------------------------------------------------------- 1 | *********************** 2 | Solver Shared Utilities 3 | *********************** 4 | 5 | .. automodule:: gEconpy.solvers.shared 6 | 7 | .. autosummary:: 8 | :toctree: generated/ 9 | 10 | stabilize 11 | o1_policy_function_adjoints 12 | pt_compute_selection_matrix 13 | -------------------------------------------------------------------------------- /docs/source/api/utilities.rst: -------------------------------------------------------------------------------- 1 | .. _api_utilities: 2 | 3 | ********* 4 | Utilities 5 | ********* 6 | 7 | .. automodule:: gEconpy.utilities 8 | 9 | .. autosummary:: 10 | :toctree: generated/ 11 | 12 | flatten_list 13 | set_equality_equals_zero 14 | eq_to_ss 15 | safe_to_ss 16 | expand_subs_for_all_times 17 | step_equation_forward 18 | step_equation_backward 19 | diff_through_time 20 | substitute_all_equations 21 | is_variable 22 | is_number 23 | unpack_keys_and_values 24 | merge_dictionaries 25 | make_all_var_time_combos 26 | postprocess_optimizer_res 27 | get_name 28 | substitute_repeatedly 29 | simplify_matrix 30 | -------------------------------------------------------------------------------- /docs/source/dev/index.rst: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | WRITEME 5 | -------------------------------------------------------------------------------- /docs/source/examples/GCN Files/RBC.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | U[], TC[]; 4 | }; 5 | 6 | 7 | block STEADY_STATE 8 | { 9 | identities 10 | { 11 | A[ss] = 1; 12 | mc[ss] = 1; 13 | r[ss] = (1 / beta - (1 - delta)); 14 | w[ss] = (1 - alpha) * (alpha / r[ss]) ^ (alpha / (1 - alpha)); 15 | Y[ss] = (r[ss] / (r[ss] - delta * alpha)) ^ (sigma_C / (sigma_C + sigma_L)) * 16 | (w[ss] * (w[ss] / (1 - alpha)) ^ sigma_L) ^ (1 / (sigma_C + sigma_L)); 17 | 18 | I[ss] = (delta * alpha / r[ss]) * Y[ss]; 19 | C[ss] = Y[ss] ^ (-sigma_L / sigma_C) * ((1 - alpha) ^ (-sigma_L) * w[ss] ^ (1 + sigma_L)) ^ (1 / sigma_C); 20 | K[ss] = alpha * Y[ss] * mc[ss] / r[ss]; 21 | L[ss] = (1 - alpha) * Y[ss] * mc[ss] / w[ss]; 22 | 23 | U[ss] = (1 / (1 - beta)) * (C[ss] ^ (1 - sigma_C) / (1 - sigma_C) - L[ss] ^ (1 + sigma_L) / (1 + sigma_L)); 24 | lambda[ss] = C[ss] ^ (-sigma_C); 25 | TC[ss] = -(r[ss] * K[ss] + w[ss] * L[ss]); 26 | }; 27 | }; 28 | 29 | 30 | block HOUSEHOLD 31 | { 32 | definitions 33 | { 34 | u[] = (C[] ^ (1 - sigma_C) / (1 - sigma_C) - L[] ^ (1 + sigma_L) / (1 + sigma_L)); 35 | }; 36 | 37 | controls 38 | { 39 | C[], L[], I[], K[]; 40 | }; 41 | 42 | objective 43 | { 44 | U[] = u[] + beta * E[][U[1]]; 45 | }; 46 | 47 | constraints 48 | { 49 | C[] + I[] = r[] * K[-1] + w[] * L[] : lambda[]; 50 | K[] = (1 - delta) * K[-1] + I[]; 51 | }; 52 | 53 | calibration 54 | { 55 | beta ~ maxent(Beta(), lower=0.95, upper=0.999, mass=0.99) = 0.99; 56 | delta ~ maxent(Beta(), lower=0.01, upper=0.05, mass=0.99) = 0.02; 57 | 58 | sigma_C ~ maxent(Gamma(), lower=1.01, upper=10.0, mass=0.99) = 1.5; 59 | sigma_L ~ maxent(Gamma(), lower=1.000, upper=10.0, mass=0.99) = 2.0; 60 | }; 61 | }; 62 | 63 | block FIRM 64 | { 65 | controls 66 | { 67 | K[-1], L[]; 68 | }; 69 | 70 | objective 71 | { 72 | TC[] = -(r[] * K[-1] + w[] * L[]); 73 | }; 74 | 75 | constraints 76 | { 77 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 78 | }; 79 | 80 | identities 81 | { 82 | # Perfect competition 83 | mc[] = 1; 84 | }; 85 | 86 | calibration 87 | { 88 | alpha ~ maxent(Beta(), lower=0.2, upper=0.5, mass=0.99) = 0.35; 89 | }; 90 | }; 91 | 92 | block TECHNOLOGY_SHOCKS 93 | { 94 | identities 95 | { 96 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 97 | }; 98 | 99 | shocks 100 | { 101 | epsilon_A[]; 102 | }; 103 | 104 | calibration 105 | { 106 | rho_A ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.95; 107 | }; 108 | }; 109 | -------------------------------------------------------------------------------- /docs/source/examples/GCN Files/RBC_backward_compat.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | U[], TC[]; 4 | }; 5 | 6 | 7 | block HOUSEHOLD 8 | { 9 | definitions 10 | { 11 | u[] = (C[] ^ (1 - sigma_C) / (1 - sigma_C) - L[] ^ (1 + sigma_L) / (1 + sigma_L)); 12 | }; 13 | 14 | controls 15 | { 16 | C[], L[], I[], K[]; 17 | }; 18 | 19 | objective 20 | { 21 | U[] = u[] + beta * E[][U[1]]; 22 | }; 23 | 24 | constraints 25 | { 26 | C[] + I[] = r[] * K[-1] + w[] * L[] : lambda[]; 27 | K[] = (1 - delta) * K[-1] + I[]; 28 | }; 29 | 30 | calibration 31 | { 32 | beta = 0.99; 33 | delta = 0.02; 34 | 35 | sigma_C = 1.5; 36 | sigma_L = 2.0; 37 | }; 38 | }; 39 | 40 | block FIRM 41 | { 42 | controls 43 | { 44 | K[-1], L[]; 45 | }; 46 | 47 | objective 48 | { 49 | TC[] = -(r[] * K[-1] + w[] * L[]); 50 | }; 51 | 52 | constraints 53 | { 54 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 55 | }; 56 | 57 | identities 58 | { 59 | # Perfect competition 60 | mc[] = 1; 61 | }; 62 | 63 | calibration 64 | { 65 | alpha = 0.35; 66 | }; 67 | }; 68 | 69 | block TECHNOLOGY_SHOCKS 70 | { 71 | identities 72 | { 73 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 74 | }; 75 | 76 | shocks 77 | { 78 | epsilon_A[]; 79 | }; 80 | 81 | calibration 82 | { 83 | rho_A = 0.95; 84 | }; 85 | }; 86 | -------------------------------------------------------------------------------- /docs/source/examples/GCN Files/RBC_extended.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | U[], TC[], q[], K_d[]; 4 | }; 5 | 6 | block STEADY_STATE 7 | { 8 | definitions 9 | { 10 | K_to_L[ss] = (alpha * A[ss] * mc[ss] / r[ss]) ^ (1 / (1 - alpha)); 11 | }; 12 | 13 | identities 14 | { 15 | A[ss] = 1; 16 | shock_I[ss] = 1; 17 | beta[ss] = beta; 18 | Theta[ss] = Theta; 19 | z[ss] = 1; 20 | mc[ss] = 1; 21 | 22 | r[ss] = (1 / beta - (1 - delta)); 23 | w[ss] = (1 - alpha) * A[ss] * mc[ss] * K_to_L[ss] ^ alpha; 24 | L[ss] = ((A[ss] * K_to_L[ss] ^ alpha - delta * K_to_L[ss]) ^ (-sigma_C) 25 | * (1 - phi_H * beta) / (1 - phi_H) ^ sigma_C 26 | * w[ss] / Theta 27 | ) ^ (1 / (sigma_C + sigma_L)); 28 | 29 | K[ss] = K_to_L[ss] * L[ss]; 30 | K_d[ss] = z[ss] * K[ss]; 31 | Y[ss] = A[ss] * K_d[ss] ^ alpha * L[ss] ^ (1 - alpha); 32 | 33 | I[ss] = delta * K[ss]; 34 | C[ss] = Y[ss] - I[ss]; 35 | 36 | U[ss] = (1 / (1 - beta)) * (C[ss] ^ (1 - sigma_C) / (1 - sigma_C) - L[ss] ^ (1 + sigma_L) / (1 + sigma_L)); 37 | lambda[ss] = (1 - phi_H * beta) / ((1 - phi_H) * C[ss]) ^ sigma_C; 38 | q[ss] = lambda[ss]; 39 | 40 | TC[ss] = -(r[ss] * K[ss] + w[ss] * L[ss]); 41 | }; 42 | }; 43 | 44 | 45 | block HOUSEHOLD 46 | { 47 | definitions 48 | { 49 | u[] = ((C[] - phi_H * C[-1]) ^ (1 - sigma_C) / (1 - sigma_C) - Theta[] * L[] ^ (1 + sigma_L) / (1 + sigma_L)); 50 | Psi_z[] = psi_z_1 * (z[] - 1) + psi_z / 2 * (z[] - 1) ^ 2; 51 | }; 52 | 53 | controls 54 | { 55 | C[], L[], I[], K[], z[]; 56 | }; 57 | 58 | objective 59 | { 60 | U[] = u[] + beta[] * E[][U[1]]; 61 | }; 62 | 63 | constraints 64 | { 65 | C[] + I[] + Psi_z[] * K[-1] = r[] * z[] * K[-1] + w[] * L[]: lambda[]; 66 | K[] = (1 - delta) * K[-1] + I[] * (1 - gamma_I / 2 * (shock_I[] * I[] / I[-1] - 1) ^ 2) : q[]; 67 | }; 68 | 69 | identities 70 | { 71 | log(beta[]) = rho_beta * log(beta[-1]) + (1 - rho_beta) * log(beta) + epsilon_beta[]; 72 | log(shock_I[]) = rho_I * log(shock_I[-1]) + epsilon_I[]; 73 | log(Theta[]) = rho_Theta * log(Theta[-1]) + (1 - rho_Theta) * log(Theta) + epsilon_Theta[]; 74 | }; 75 | 76 | shocks 77 | { 78 | epsilon_beta[], epsilon_I[], epsilon_Theta[]; 79 | }; 80 | 81 | 82 | calibration 83 | { 84 | beta ~ maxent(Beta(), lower=0.95, upper=0.99, mass=0.99) = 0.99; 85 | delta ~ maxent(Beta(), lower=0.01, upper=0.05, mass=0.99) = 0.035; 86 | 87 | sigma_C ~ maxent(Gamma(), lower=1.5, upper=5.0, mass=0.99) = 3; 88 | sigma_L ~ maxent(Gamma(), lower=1.0, upper=5.0, mass=0.99) = 1.5; 89 | 90 | Theta ~ maxent(Gamma(), lower=0.8, upper=1.5, mass=0.99) = 1.0; 91 | gamma_I ~ maxent(Gamma(), lower=3.0, upper=10.0) = 6.32; 92 | phi_H ~ maxent(Beta(), lower=0.7, upper=0.99, mass=0.99) = 0.8; 93 | 94 | rho_beta ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 95 | rho_Theta ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 96 | rho_I ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.9; 97 | psi_z ~ maxent(Beta(), lower=0.05, upper=0.30) = 0.169; 98 | 99 | # Choose this to be r[ss] so that z[] has no effect on the steady-state 100 | psi_z_1 = 1 / beta - (1 - delta); 101 | }; 102 | }; 103 | 104 | block FIRM 105 | { 106 | controls 107 | { 108 | K_d[], L[]; 109 | }; 110 | 111 | objective 112 | { 113 | TC[] = -(r[] * K_d[] + w[] * L[]); 114 | }; 115 | 116 | constraints 117 | { 118 | Y[] = A[] * K_d[] ^ alpha * L[] ^ (1 - alpha) : mc[]; 119 | }; 120 | 121 | identities 122 | { 123 | # Perfect competition 124 | mc[] = 1; 125 | K_d[] = z[] * K[-1]; 126 | }; 127 | 128 | calibration 129 | { 130 | alpha ~ maxent(Beta(), lower=0.2, upper=0.5, mass=0.99) = 0.35; 131 | }; 132 | }; 133 | 134 | block TECHNOLOGY_SHOCKS 135 | { 136 | identities 137 | { 138 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 139 | }; 140 | 141 | shocks 142 | { 143 | epsilon_A[]; 144 | }; 145 | 146 | calibration 147 | { 148 | rho_A ~ Beta(mu=0.95, sigma=0.04) = 0.95; 149 | }; 150 | }; 151 | -------------------------------------------------------------------------------- /docs/source/examples/GCN Files/RBC_two_household.gcn: -------------------------------------------------------------------------------- 1 | assumptions 2 | { 3 | positive 4 | { 5 | Y[], K[], C_NR[], C_R[], 6 | w[], r[], 7 | L[], L_NR[], L_R[], 8 | TFP[], 9 | alpha, beta, sigma_C, sigma_L, delta, omega; 10 | }; 11 | }; 12 | 13 | tryreduce 14 | { 15 | U_NR[], U_R[], TC[]; 16 | }; 17 | 18 | block STEADY_STATE 19 | { 20 | identities 21 | { 22 | TFP[ss] = 1.0; 23 | shock_beta_R[ss] = 1.0; 24 | 25 | r[ss] = 1 / beta - (1 - delta); 26 | w[ss] = (1 - alpha) * (alpha / r[ss]) ^ (alpha / (1 - alpha)); 27 | mc[ss] = 1; 28 | Y[ss] = (r[ss] / (r[ss] - delta * alpha)) ^ (sigma_C / (sigma_C + sigma_L)) * 29 | (w[ss] * (w[ss] / (1 - alpha)) ^ sigma_L) ^ (1 / (sigma_C + sigma_L)); 30 | 31 | I[ss] = (delta * alpha / r[ss]) * Y[ss]; 32 | C[ss] = Y[ss] ^ (-sigma_L / sigma_C) * ((1 - alpha) ^ (-sigma_L) * w[ss] ^ (1 + sigma_L)) ^ (1 / sigma_C); 33 | K[ss] = alpha * Y[ss] * mc[ss] / r[ss]; 34 | L[ss] = (1 - alpha) * Y[ss] * mc[ss] / w[ss]; 35 | 36 | TC[ss] = -(r[ss] * K[ss] + w[ss] * L[ss]); 37 | }; 38 | }; 39 | 40 | block RICARDIAN_HOUSEHOLD 41 | { 42 | definitions 43 | { 44 | u_R[] = shock_beta_R[] * (C_R[] ^ (1 - sigma_C) / (1 - sigma_C) - 45 | L_R[] ^ (1 + sigma_L) / (1 + sigma_L)); 46 | }; 47 | 48 | controls 49 | { 50 | C_R[], L_R[], I[], K[]; 51 | }; 52 | 53 | objective 54 | { 55 | U_R[] = u_R[] + beta * E[][U_R[1]]; 56 | }; 57 | 58 | constraints 59 | { 60 | @exclude 61 | C_R[] + I[] = r[] * K[-1] + w[] * L_R[] : lambda_R[]; 62 | 63 | K[] = (1 - delta) * K[-1] + I[]: q[]; 64 | }; 65 | 66 | identities 67 | { 68 | log(shock_beta_R[]) = rho_beta_R * log(shock_beta_R[-1]) + epsilon_beta_R[]; 69 | }; 70 | 71 | shocks 72 | { 73 | epsilon_beta_R[]; 74 | }; 75 | 76 | calibration 77 | { 78 | beta = 0.99; 79 | delta = 0.02; 80 | sigma_C = 1.5; 81 | sigma_L = 2.0; 82 | rho_beta_R = 0.95; 83 | }; 84 | }; 85 | 86 | block NON_RICARDIAN_HOUSEHOLD 87 | { 88 | definitions 89 | { 90 | u_NR[] = (C_NR[] ^ (1 - sigma_C) / (1 - sigma_C) - 91 | L_NR[] ^ (1 + sigma_L) / (1 + sigma_L)); 92 | }; 93 | 94 | controls 95 | { 96 | C_NR[], L_NR[]; 97 | }; 98 | 99 | objective 100 | { 101 | U_NR[] = u_NR[] + beta * E[][U_NR[1]]; 102 | }; 103 | 104 | constraints 105 | { 106 | C_NR[] = w[] * L_NR[]: lambda_NR[]; 107 | }; 108 | }; 109 | 110 | 111 | block FIRM 112 | { 113 | controls 114 | { 115 | K[-1], L[]; 116 | }; 117 | 118 | objective 119 | { 120 | TC[] = -(r[] * K[-1] + w[] * L[]); 121 | }; 122 | 123 | constraints 124 | { 125 | Y[] = TFP[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 126 | }; 127 | 128 | identities 129 | { 130 | # Perfect competition 131 | mc[] = 1; 132 | 133 | # Exogenous technology process 134 | log(TFP[]) = rho_TFP * log(TFP[-1]) + epsilon_TFP[]; 135 | }; 136 | 137 | shocks 138 | { 139 | epsilon_TFP[]; 140 | }; 141 | 142 | calibration 143 | { 144 | alpha = 0.35; 145 | 146 | rho_TFP = 0.95; 147 | }; 148 | }; 149 | 150 | block EQULIBRIUM 151 | { 152 | identities 153 | { 154 | Y[] = C[] + I[]; 155 | L[] = omega * L_R[] + (1 - omega) * L_NR[]; 156 | C[] = omega * C_R[] + (1 - omega) * C_NR[]; 157 | }; 158 | 159 | calibration 160 | { 161 | omega = 0.5; 162 | }; 163 | }; 164 | -------------------------------------------------------------------------------- /docs/source/examples/GCN Files/RBC_two_household_additive.gcn: -------------------------------------------------------------------------------- 1 | assumptions 2 | { 3 | positive 4 | { 5 | Y[], K[], C_NR[], C_R[], 6 | w[], r[], 7 | L[], L_NR[], L_R[], 8 | TFP[], 9 | alpha, alpha_L, beta, sigma_C, sigma_L, delta; 10 | }; 11 | }; 12 | 13 | tryreduce 14 | { 15 | U_NR[], U_R[], TC[]; 16 | }; 17 | 18 | block STEADY_STATE 19 | { 20 | definitions 21 | { 22 | # Capital/Labor ratio, N = K/L 23 | N[ss] = (alpha * TFP[ss] / r[ss]) ^ (1 / (1 - alpha)); 24 | 25 | }; 26 | identities 27 | { 28 | TFP[ss] = 1.0; 29 | shock_beta_R[ss] = 1.0; 30 | Theta_R[ss] = Theta_R; 31 | Theta_N[ss] = Theta_N; 32 | 33 | r[ss] = 1 / beta - (1 - delta); 34 | w[ss] = (1 - alpha) * N[ss] ^ alpha; 35 | 36 | C_R[ss] = (w[ss] / Theta_R) ^ (1 / sigma_R); 37 | C_NR[ss] = (w[ss] / Theta_N) ^ (1 / sigma_N); 38 | 39 | C[ss] = omega * C_R[ss] + (1 - omega) * C_NR[ss]; 40 | L[ss] = C[ss] / (N[ss] ^ alpha - delta * N[ss]); 41 | L_NR[ss] = C_NR[ss] / w[ss]; 42 | L_R[ss] = (L[ss] - (1 - omega) * L_NR[ss]) / omega; 43 | 44 | K[ss] = N[ss] * L[ss]; 45 | I[ss] = delta * K[ss]; 46 | Y[ss] = C[ss] + I[ss]; 47 | 48 | lambda_R[ss] = C_R[ss] ^ -sigma_R; 49 | lambda_NR[ss] = C_NR[ss] ^ -sigma_N; 50 | q[ss] = lambda_R[ss]; 51 | }; 52 | }; 53 | 54 | block RICARDIAN_HOUSEHOLD 55 | { 56 | definitions 57 | { 58 | u_R[] = shock_beta_R[] * (C_R[] ^ (1 - sigma_R) / (1 - sigma_R) - Theta_R[] * L_R[]); 59 | }; 60 | 61 | controls 62 | { 63 | C_R[], L_R[], I[], K[]; 64 | }; 65 | 66 | objective 67 | { 68 | U_R[] = u_R[] + beta * E[][U_R[1]]; 69 | }; 70 | 71 | constraints 72 | { 73 | @exclude 74 | C_R[] + I[] = r[] * K[-1] + w[] * L_R[] : lambda_R[]; 75 | 76 | K[] = (1 - delta) * K[-1] + I[]: q[]; 77 | }; 78 | 79 | identities 80 | { 81 | log(shock_beta_R[]) = rho_beta_R * log(shock_beta_R[-1]) + epsilon_beta_R[]; 82 | log(Theta_R[]) = (1 - rho_Theta_R) * log(Theta_R) + rho_Theta_R * log(Theta_R[-1]) + epsilon_Theta_R[]; 83 | }; 84 | 85 | shocks 86 | { 87 | epsilon_beta_R[], epsilon_Theta_R[]; 88 | }; 89 | 90 | calibration 91 | { 92 | beta ~ maxent(Beta(), lower=0.90, upper=0.99) = 0.99; 93 | delta ~ maxent(Beta(), lower=0.01, upper=0.05) = 0.02; 94 | sigma_R ~ maxent(Gamma(), lower=1.1, upper=3.0) = 1.5; 95 | Theta_R ~ maxent(Gamma(), lower=0.1, upper=5.0) = 1.0; 96 | rho_beta_R ~ maxent(Beta(), lower=0.5, upper=0.99) = 0.95; 97 | rho_Theta_R ~ maxent(Beta(), lower=0.5, upper=0.99) = 0.95; 98 | }; 99 | }; 100 | 101 | block NON_RICARDIAN_HOUSEHOLD 102 | { 103 | definitions 104 | { 105 | u_NR[] = C_NR[] ^ (1 - sigma_N) / (1 - sigma_N) - Theta_N[] * L_NR[]; 106 | }; 107 | 108 | controls 109 | { 110 | C_NR[], L_NR[]; 111 | }; 112 | 113 | objective 114 | { 115 | U_NR[] = u_NR[] + beta * E[][U_NR[1]]; 116 | }; 117 | 118 | constraints 119 | { 120 | C_NR[] = w[] * L_NR[]: lambda_NR[]; 121 | }; 122 | 123 | identities 124 | { 125 | log(Theta_N[]) = (1 - rho_Theta_N) * log(Theta_N) + rho_Theta_N * log(Theta_N[-1]) + epsilon_Theta_N[]; 126 | }; 127 | 128 | shocks 129 | { 130 | epsilon_Theta_N[]; 131 | }; 132 | 133 | calibration 134 | { 135 | Theta_N ~ maxent(Gamma(), lower=0.1, upper=5.0) = 1.0; 136 | sigma_N ~ maxent(Gamma(), lower=1.1, upper=3.0) = 1.5; 137 | 138 | rho_Theta_N ~ maxent(Beta(), lower=0.5, upper=0.99) = 0.95; 139 | }; 140 | }; 141 | 142 | 143 | block FIRM 144 | { 145 | controls 146 | { 147 | K[-1], L[]; 148 | }; 149 | 150 | objective 151 | { 152 | TC[] = -(r[] * K[-1] + w[] * L[]); 153 | }; 154 | 155 | constraints 156 | { 157 | Y[] = TFP[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 158 | }; 159 | 160 | identities 161 | { 162 | # Perfect competition 163 | mc[] = 1; 164 | 165 | # Exogenous technology process 166 | log(TFP[]) = rho_TFP * log(TFP[-1]) + epsilon_TFP[]; 167 | }; 168 | 169 | shocks 170 | { 171 | epsilon_TFP[]; 172 | }; 173 | 174 | calibration 175 | { 176 | alpha ~ maxent(Beta(), lower=0.3, upper=0.6) = 0.35; 177 | rho_TFP ~ maxent(Beta(), lower=0.8, upper=0.99) = 0.95; 178 | }; 179 | }; 180 | 181 | block EQULIBRIUM 182 | { 183 | identities 184 | { 185 | Y[] = C[] + I[]; 186 | L[] = omega * L_R[] + (1 - omega) * L_NR[]; 187 | C[] = omega * C_R[] + (1 - omega) * C_NR[]; 188 | }; 189 | 190 | calibration 191 | { 192 | omega ~ maxent(Beta(), lower=0.6, upper=0.99) = 0.66; 193 | }; 194 | }; 195 | -------------------------------------------------------------------------------- /docs/source/examples/GCN Files/RBC_with_CES.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | U[], TC[]; 4 | }; 5 | 6 | assumptions 7 | { 8 | positive 9 | { 10 | A[], Y[], C[], K[], L[], w[], r[], mc[], beta, delta, sigma_C, sigma_L, alpha, psi; 11 | }; 12 | }; 13 | 14 | block STEADY_STATE 15 | { 16 | definitions 17 | { 18 | f1[ss] = r[ss] ^ (psi - 1) * alpha ^ ((1 - psi) / psi) * (A[ss] * mc[ss]) ^ (1 - psi); 19 | N[ss] = ((f1[ss] - alpha ^ (1 / psi)) / (1 - alpha) ^ (1 / psi)) ^ (psi / (1 - psi)); 20 | f2[ss] = alpha ^ (1 / psi) * N[ss] ^ ((psi - 1) / psi) + (1 - alpha) ^ (1 / psi); 21 | }; 22 | 23 | identities 24 | { 25 | A[ss] = 1.0; 26 | r[ss] = 1 / beta - (1 - delta); 27 | mc[ss] = 1.0; 28 | 29 | w[ss] = (1 - alpha) ^ (1 / psi) * A[ss] * mc[ss] * f2[ss] ^ (1 / (psi - 1)); 30 | 31 | L[ss] = (w[ss] / Theta) ^ (1 / (sigma_L + sigma_C)) * 32 | (A[ss] * f2[ss] ^ (psi / (psi - 1)) - delta * N[ss]) ^ (-sigma_C / (sigma_L + sigma_C)); 33 | 34 | K[ss] = N[ss] * L[ss]; 35 | I[ss] = delta * K[ss]; 36 | Y[ss] = A[ss] * (alpha ^ (1 / psi) * K[ss] ^ ((psi - 1) / psi) + 37 | (1 - alpha) ^ (1 / psi) * L[ss] ^ ((psi - 1) / psi)) ^ (psi / (psi - 1)); 38 | C[ss] = Y[ss] - I[ss]; 39 | 40 | lambda[ss] = C[ss] ^ (-sigma_C); 41 | }; 42 | 43 | }; 44 | 45 | block HOUSEHOLD 46 | { 47 | definitions 48 | { 49 | u[] = C[] ^ (1 - sigma_C) / (1 - sigma_C) - Theta * L[] ^ (1 + sigma_L) / (1 + sigma_L); 50 | }; 51 | 52 | controls 53 | { 54 | C[], L[], I[], K[]; 55 | }; 56 | 57 | objective 58 | { 59 | U[] = u[] + beta * E[][U[1]]; 60 | }; 61 | 62 | constraints 63 | { 64 | C[] + I[] = r[] * K[-1] + w[] * L[] : lambda[]; 65 | 66 | K[] = (1 - delta) * K[-1] + I[]; 67 | }; 68 | 69 | calibration 70 | { 71 | beta = 0.99; 72 | delta = 0.02; 73 | sigma_C = 1.5; 74 | sigma_L = 2.0; 75 | Theta = 1.0; 76 | }; 77 | }; 78 | 79 | block FIRM 80 | { 81 | controls 82 | { 83 | K[-1], L[]; 84 | }; 85 | 86 | objective 87 | { 88 | TC[] = -(r[] * K[-1] + w[] * L[]); 89 | }; 90 | 91 | constraints 92 | { 93 | Y[] = A[] * (alpha ^ (1 / psi) * K[-1] ^ ((psi - 1) / psi) + 94 | (1 - alpha) ^ (1 / psi) * L[] ^ ((psi - 1) / psi) 95 | ) ^ (psi / (psi - 1)): mc[]; 96 | }; 97 | 98 | identities 99 | { 100 | # Perfect competition 101 | mc[] = 1; 102 | }; 103 | 104 | calibration 105 | { 106 | alpha = 0.35; 107 | psi = 0.6; 108 | }; 109 | }; 110 | 111 | block TECHNOLOGY_SHOCKS 112 | { 113 | identities 114 | { 115 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 116 | }; 117 | 118 | shocks 119 | { 120 | epsilon_A[]; 121 | }; 122 | 123 | calibration 124 | { 125 | rho_A = 0.95; 126 | }; 127 | }; 128 | -------------------------------------------------------------------------------- /docs/source/get_started/about.rst: -------------------------------------------------------------------------------- 1 | About gEconpy 2 | ============= 3 | 4 | WRITEME 5 | -------------------------------------------------------------------------------- /docs/source/get_started/index.rst: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | install 8 | about 9 | overview 10 | -------------------------------------------------------------------------------- /docs/source/get_started/install.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | 5 | Recommended Installation Method 6 | ******************************* 7 | You can use the ``environment.yaml`` file provided in the repository to create a new conda environment with all the 8 | dependencies installed: 9 | 10 | .. code-block:: bash 11 | 12 | conda env create -f environment.yaml 13 | conda activate gEconpy 14 | 15 | 16 | Other Methods 17 | ************* 18 | ``gEconpy`` is available on PyPI and can be installed using pip: 19 | 20 | .. code-block:: bash 21 | 22 | pip install gEconpy 23 | 24 | This command will install the package and all its dependencies. Is is **strongly** recommended that you create a 25 | virtual environment before installing the package. ``gEconpy`` depends on `pytensor `_, 26 | a package that requires a C compiler to be installed on your system. Therefore, it is recommended that you first create a virtual environment with 27 | pytensor, then install ``gEconpy`` in that environment: 28 | 29 | .. code-block:: bash 30 | 31 | conda create -n geconpy "python=3.12" pip pytensor 32 | conda activate geconpy 33 | pip install gEconpy 34 | 35 | 36 | This will ensure that all dependencies are correctly installed and that the package will work as expected. 37 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | A collection of tools for working with DSGE models in python, inspired by the fantastic R package gEcon, http://gecon.r-forge.r-project.org/. 4 | 5 | Like gEcon, gEconpy solves first order conditions automatically, helping the researcher avoid math errors while facilitating rapid prototyping of models. By working in the optimization problem space rather than the FoC space, modifications to the model are much simpler. Adding an additional term to the utility function, for example, requires modifying only 2-3 lines of code, whereas in FoC space it may require re-solving the entire model by hand. 6 | 7 | gEconpy uses the GCN file originally created for the gEcon package. gEcon GCN files are fully compatable with gEconpy, and includes all the great features of GCN files, including: 8 | 9 | * Automatically solve first order conditions 10 | * Users can include steady-state values in equations without explictly solving for them by hand first! 11 | * Users can declare "calibrated parameters", requesting a parameter value be found to induce a specific steady-state relationship 12 | 13 | gEconpy is still in an unfinished alpha state, but I encourage anyone interested in DSGE modeling to give it a try and and report any bugs you might find. 14 | 15 | 16 | Quick Setup 17 | =========== 18 | gEconpy is available on PyPi, and can be installed with pip: 19 | 20 | .. code-block:: bash 21 | 22 | pip install gEconpy 23 | 24 | 25 | For more detailed installation instructions, see the :doc:`installation guide `. 26 | 27 | 28 | Citation 29 | ======== 30 | 31 | If you use gEconpy in your research, please cite the package using the following BibTeX entry: 32 | 33 | .. code-block:: bibtex 34 | 35 | @software{gEconpy, 36 | author = {Jesse Grabowski}, 37 | title = {gEconpy: A collection of tools for working with DSGE models in python}, 38 | url = {https://github.com/jessegrabowski/gEconpy}, 39 | version = {1.2.0}} 40 | 41 | .. toctree:: 42 | :maxdepth: 1 43 | :hidden: 44 | :titlesonly: 45 | 46 | get_started/index 47 | user_guide/index 48 | examples/gallery 49 | api 50 | dev/index 51 | release/index 52 | -------------------------------------------------------------------------------- /docs/source/install.rst: -------------------------------------------------------------------------------- 1 | gEconpy is available on PyPi, and can be installed with pip: 2 | 3 | .. code-block:: bash 4 | 5 | pip install gEconpy 6 | -------------------------------------------------------------------------------- /docs/source/release/index.rst: -------------------------------------------------------------------------------- 1 | .. _release_index: 2 | 3 | ============= 4 | Release Notes 5 | ============= 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | -------------------------------------------------------------------------------- /docs/source/user_guide/dsge_intro.rst: -------------------------------------------------------------------------------- 1 | Introduction to DSGE Modeling 2 | ============================= 3 | 4 | WRITEME 5 | -------------------------------------------------------------------------------- /docs/source/user_guide/estimation.rst: -------------------------------------------------------------------------------- 1 | Estimation of a DSGE Model 2 | =========================== 3 | 4 | WRITEME 5 | -------------------------------------------------------------------------------- /docs/source/user_guide/example_model.rst: -------------------------------------------------------------------------------- 1 | A Simple Modeling Workflow 2 | ========================== 3 | 4 | WRITEME 5 | -------------------------------------------------------------------------------- /docs/source/user_guide/index.rst: -------------------------------------------------------------------------------- 1 | User Guide 2 | ========== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | dsge_intro 8 | gcn_files 9 | example_model 10 | estimation 11 | -------------------------------------------------------------------------------- /gEconpy/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import sys 3 | 4 | from gEconpy import ( 5 | classes, 6 | numbaf, # noqa: F401 7 | parser, 8 | plotting, 9 | solvers, 10 | utilities, 11 | ) 12 | from gEconpy._version import get_versions 13 | from gEconpy.dynare_convert import make_mod_file 14 | from gEconpy.model.build import model_from_gcn, statespace_from_gcn 15 | from gEconpy.model.model import ( 16 | autocorrelation_matrix, 17 | autocovariance_matrix, 18 | check_bk_condition, 19 | check_steady_state, 20 | impulse_response_function, 21 | matrix_to_dataframe, 22 | simulate, 23 | stationary_covariance_matrix, 24 | summarize_perturbation_solution, 25 | ) 26 | from gEconpy.model.statespace import data_from_prior 27 | from gEconpy.model.steady_state import print_steady_state 28 | from gEconpy.parser.html import print_gcn_file 29 | 30 | _log = logging.getLogger(__name__) 31 | 32 | if not logging.root.handlers: 33 | _log.setLevel(logging.INFO) 34 | if len(_log.handlers) == 0: 35 | handler = logging.StreamHandler(sys.stderr) 36 | _log.addHandler(handler) 37 | 38 | 39 | __version__ = get_versions()["version"] 40 | 41 | __all__ = [ 42 | "autocorrelation_matrix", 43 | "autocovariance_matrix", 44 | "check_bk_condition", 45 | "check_steady_state", 46 | "classes", 47 | "data_from_prior", 48 | "exceptions", 49 | "impulse_response_function", 50 | "make_mod_file", 51 | "matrix_to_dataframe", 52 | "model_from_gcn", 53 | "parser", 54 | "plotting", 55 | "print_gcn_file", 56 | "print_steady_state", 57 | "simulate", 58 | "solvers", 59 | "statespace_from_gcn", 60 | "stationary_covariance_matrix", 61 | "summarize_perturbation_solution", 62 | "utilities", 63 | ] 64 | -------------------------------------------------------------------------------- /gEconpy/classes/__init__.py: -------------------------------------------------------------------------------- 1 | # from gEconpy.model.model import gEconModel 2 | # 3 | # __all__ = ["gEconModel"] 4 | -------------------------------------------------------------------------------- /gEconpy/classes/time_aware_symbol.py: -------------------------------------------------------------------------------- 1 | import sympy as sp 2 | 3 | from sympy.core.cache import cacheit 4 | 5 | 6 | class TimeAwareSymbol(sp.Symbol): 7 | """ 8 | Subclass of :class:`sympy.Symbol` with a time index. 9 | 10 | A TimeAwareSymbol is identical to a :class:`symPy.Symbol` in all respects, except that it has a 11 | time index property that is used when determining equality and hashability. Two symbols with the same name, 12 | assumptions, and time index evaluate to equal. 13 | 14 | Examples 15 | -------- 16 | 17 | .. code-block:: python 18 | 19 | from gEconpy.classes.time_aware_symbol import TimeAwareSymbol 20 | x1 = TimeAwareSymbol("x", time_index=1) 21 | x2 = TimeAwareSymbol("x", time_index=2) 22 | 23 | print(x1 == x2) # False, time indexes are different 24 | print(x1 == x2.set_t(1)) # True, time indexes are the same 25 | print(x1.step_forward() == x2) # True, time indexes are the same 26 | """ 27 | 28 | __slots__ = ("__dict__", "base_name", "time_index") 29 | time_index: int | str 30 | base_name: str 31 | safe_name: str 32 | 33 | def __new__(cls, name, time_index, **assumptions): 34 | cls._sanitize(assumptions, cls) 35 | 36 | return TimeAwareSymbol.__xnew__(cls, name, time_index, **assumptions) 37 | 38 | def __getnewargs__(self): 39 | return self.name, self.time_index 40 | 41 | def _numpycode(self, *args, **kwargs): 42 | return self.safe_name 43 | 44 | @staticmethod 45 | @cacheit 46 | def __xnew__(cls, name, time_index, **assumptions): 47 | obj = super().__xnew__(cls, name, **assumptions) 48 | obj.time_index = time_index 49 | obj.base_name = name 50 | obj.name = obj._create_name_from_time_index() 51 | obj.safe_name = obj.name.replace("+", "p").replace("-", "m") 52 | return obj 53 | 54 | def _determine_operator(self): 55 | if self.time_index == "ss": 56 | return "" 57 | if self.time_index > 0: 58 | operator = "+" 59 | elif self.time_index < 0: 60 | operator = "-" 61 | else: 62 | operator = "" 63 | return operator 64 | 65 | def _create_name_from_time_index(self): 66 | operator = self._determine_operator() 67 | name = self.base_name 68 | idx = self.time_index 69 | idx = idx if isinstance(idx, str) else str(abs(idx)) 70 | 71 | if idx == "ss": 72 | time_name = rf"{name}_{idx}" 73 | elif idx == "0": 74 | time_name = rf"{name}_t" 75 | else: 76 | time_name = rf"{name}_t{operator}{idx}" 77 | 78 | return time_name 79 | 80 | def _hashable_content(self): 81 | return (*super()._hashable_content(), self.time_index) 82 | 83 | def __getnewargs_ex__(self): 84 | return ( 85 | ( 86 | self.base_name, 87 | self.time_index, 88 | ), 89 | self.assumptions0, 90 | ) 91 | 92 | def step_forward(self): 93 | """ 94 | Increment the time index by one. 95 | """ 96 | obj = TimeAwareSymbol(self.base_name, self.time_index + 1, **self.assumptions0) 97 | return obj 98 | 99 | def step_backward(self): 100 | """ 101 | Decrement the time index by one. 102 | """ 103 | obj = TimeAwareSymbol(self.base_name, self.time_index - 1, **self.assumptions0) 104 | return obj 105 | 106 | def to_ss(self): 107 | """ 108 | Set the time index to steady state. 109 | 110 | Once in the steady state, :meth:`step_forward` and :meth:`step_backward` will not change the time index. 111 | """ 112 | obj = TimeAwareSymbol(self.base_name, "ss", **self.assumptions0) 113 | return obj 114 | 115 | def exit_ss(self): 116 | """ 117 | Set the time index to zero if in the steady state, otherwise do nothing. 118 | """ 119 | if self.time_index == "ss": 120 | obj = TimeAwareSymbol(self.base_name, 0, **self.assumptions0) 121 | else: 122 | obj = self 123 | return obj 124 | 125 | def set_t(self, t): 126 | """ 127 | Set the time index to a specific value. 128 | 129 | Parameters 130 | ---------- 131 | t: int | str 132 | The time index to set. If str, must be "ss" . 133 | """ 134 | if isinstance(t, str) and t != "ss": 135 | raise ValueError("Time index must be an integer or 'ss'.") 136 | obj = TimeAwareSymbol(self.base_name, t, **self.assumptions0) 137 | return obj 138 | -------------------------------------------------------------------------------- /gEconpy/model/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/gEconpy/model/__init__.py -------------------------------------------------------------------------------- /gEconpy/model/parameters.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Callable 2 | 3 | from gEconpy.classes.containers import SymbolDictionary 4 | from gEconpy.model.compile import ( 5 | BACKENDS, 6 | compile_function, 7 | dictionary_return_wrapper, 8 | make_return_dict_and_update_cache, 9 | ) 10 | 11 | 12 | def compile_param_dict_func( 13 | param_dict: SymbolDictionary, 14 | deterministic_dict: SymbolDictionary, 15 | backend: BACKENDS = "numpy", 16 | cache: dict | None = None, 17 | return_symbolic: bool = False, 18 | ) -> tuple[Callable, dict]: 19 | """ 20 | Compile a function to compute model parameters from given "free" parameters. 21 | 22 | Most model parameters are provided by the user as fixed values. We denote these are "free" parameters. Others are 23 | functions of the free parameters, and need to be dynamically recomputed each time the free parameters change. 24 | 25 | Parameters 26 | ---------- 27 | param_dict: SymbolDictionary 28 | A dictionary of free parameters. 29 | deterministic_dict: SymbolDictionary 30 | A dictionary of deterministic parameters, with the keys being the parameters and the values being the 31 | expressions to compute them. 32 | backend: str, one of "numpy", "numba", "pytensor" 33 | The backend to use for the compiled function. 34 | cache: dict, optional 35 | A dictionary mapping from pytensor symbols to sympy expressions. Used to prevent duplicate mappings from 36 | sympy symbol to pytensor symbol from being created. Default is a empty dictionary, implying no other functions 37 | have been compiled yet. 38 | return_symbolic: bool, default False 39 | When true, if backend is "pytensor", return a symbolic graph representing the computation of parameter values 40 | rather than a compiled pytensor function. Ignored if backend is not "pytensor" 41 | 42 | Returns 43 | ------- 44 | f: Callable 45 | A function that takes the free parameters as keyword arguments and returns a dictionary of the computed 46 | parameters. 47 | cache: dict 48 | A dictionary mapping from sympy symbols to pytensor symbols. 49 | """ 50 | cache = {} if cache is None else cache 51 | 52 | inputs = list(param_dict.to_sympy().keys()) 53 | output_params = inputs + list(deterministic_dict.to_sympy().keys()) 54 | output_exprs = inputs + list(deterministic_dict.values_to_float().values()) 55 | 56 | f, cache = compile_function( 57 | inputs, 58 | output_exprs, 59 | backend=backend, 60 | cache=cache, 61 | return_symbolic=return_symbolic, 62 | pop_return=False, 63 | stack_return=not return_symbolic, 64 | ) 65 | 66 | if return_symbolic and backend == "pytensor": 67 | return make_return_dict_and_update_cache(output_params, f, cache) 68 | 69 | return dictionary_return_wrapper(f, output_params), cache 70 | -------------------------------------------------------------------------------- /gEconpy/numbaf/__init__.py: -------------------------------------------------------------------------------- 1 | from gEconpy.numbaf.overloads import ( 2 | nb_ordqz, 3 | nb_qz, 4 | nb_schur, 5 | nb_solve_continuous_lyapunov, 6 | nb_solve_discrete_lyapunov, 7 | nb_solve_triangular, 8 | ) 9 | 10 | __all__ = [ 11 | "nb_ordqz", 12 | "nb_qz", 13 | "nb_schur", 14 | "nb_solve_continuous_lyapunov", 15 | "nb_solve_discrete_lyapunov", 16 | "nb_solve_triangular", 17 | ] 18 | -------------------------------------------------------------------------------- /gEconpy/numbaf/intrinsics.py: -------------------------------------------------------------------------------- 1 | from numba.core import cgutils, types 2 | from numba.extending import intrinsic 3 | 4 | 5 | @intrinsic 6 | def val_to_dptr(typingctx, data): 7 | def impl(context, builder, signature, args): 8 | ptr = cgutils.alloca_once_value(builder, args[0]) 9 | return ptr 10 | 11 | sig = types.CPointer(types.float64)(types.float64) 12 | return sig, impl 13 | 14 | 15 | @intrinsic 16 | def val_to_zptr(typingctx, data): 17 | def impl(context, builder, signature, args): 18 | ptr = cgutils.alloca_once_value(builder, args[0]) 19 | return ptr 20 | 21 | sig = types.CPointer(types.complex128)(types.complex128) 22 | return sig, impl 23 | 24 | 25 | @intrinsic 26 | def val_to_sptr(typingctx, data): 27 | def impl(context, builder, signature, args): 28 | ptr = cgutils.alloca_once_value(builder, args[0]) 29 | return ptr 30 | 31 | sig = types.CPointer(types.float32)(types.float32) 32 | return sig, impl 33 | 34 | 35 | @intrinsic 36 | def val_to_int_ptr(typingctx, data): 37 | def impl(context, builder, signature, args): 38 | ptr = cgutils.alloca_once_value(builder, args[0]) 39 | return ptr 40 | 41 | sig = types.CPointer(types.int32)(types.int32) 42 | return sig, impl 43 | 44 | 45 | @intrinsic 46 | def int_ptr_to_val(typingctx, data): 47 | def impl(context, builder, signature, args): 48 | val = builder.load(args[0]) 49 | return val 50 | 51 | sig = types.int32(types.CPointer(types.int32)) 52 | return sig, impl 53 | 54 | 55 | @intrinsic 56 | def dptr_to_val(typingctx, data): 57 | def impl(context, builder, signature, args): 58 | val = builder.load(args[0]) 59 | return val 60 | 61 | sig = types.float64(types.CPointer(types.float64)) 62 | return sig, impl 63 | 64 | 65 | @intrinsic 66 | def sptr_to_val(typingctx, data): 67 | def impl(context, builder, signature, args): 68 | val = builder.load(args[0]) 69 | return val 70 | 71 | sig = types.float32(types.CPointer(types.float32)) 72 | return sig, impl 73 | -------------------------------------------------------------------------------- /gEconpy/parser/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/gEconpy/parser/__init__.py -------------------------------------------------------------------------------- /gEconpy/parser/constants.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import sympy as sp 4 | 5 | from sympy.abc import _clash1, _clash2 6 | 7 | LOCAL_DICT = {} 8 | for letter in _clash1.keys(): 9 | LOCAL_DICT[letter] = sp.Symbol(letter) 10 | for letter in _clash2.keys(): 11 | LOCAL_DICT[letter] = sp.Symbol(letter) 12 | 13 | OPERATORS = re.escape("+-*/^=();:") 14 | 15 | BLOCK_START_TOKEN = "{" 16 | BLOCK_END_TOKEN = "};" 17 | LAG_TOKEN = "[-1]" 18 | LEAD_TOKEN = "[1]" 19 | SS_TOKEN = "[ss]" 20 | EXPECTATION_TOKEN = "E[]" 21 | CALIBRATING_EQ_TOKEN = "->" 22 | 23 | 24 | SPECIAL_BLOCK_NAMES = ["OPTIONS", "TRYREDUCE", "ASSUMPTIONS"] 25 | STEADY_STATE_NAMES = ["STEADY_STATE", "SS", "STEADYSTATE", "STEADY"] 26 | BLOCK_COMPONENTS = [ 27 | "DEFINITIONS", 28 | "CONTROLS", 29 | "OBJECTIVE", 30 | "CONSTRAINTS", 31 | "IDENTITIES", 32 | "SHOCKS", 33 | "CALIBRATION", 34 | ] 35 | 36 | TIME_INDEX_DICT = {"ss": "ss", "t": 0, "tL1": -1, "t1": 1} 37 | 38 | SYMPY_ASSUMPTIONS = [ 39 | "finite", 40 | "infinite", 41 | "even", 42 | "odd", 43 | "prime", 44 | "composite", 45 | "positive", 46 | "negative", 47 | "zero", 48 | "nonzero", 49 | "nonpositive", 50 | "nonnegative", 51 | "integer", 52 | "rational", 53 | "irrational", 54 | "real", 55 | "extended real", 56 | "hermitian", 57 | "complex", 58 | "imaginary", 59 | "antihermitian", 60 | "algebraic", 61 | "transcendental", 62 | ] 63 | 64 | DEFAULT_ASSUMPTIONS = {"real": True} 65 | -------------------------------------------------------------------------------- /gEconpy/parser/dist_syntax.py: -------------------------------------------------------------------------------- 1 | import pyparsing as pp 2 | 3 | from gEconpy.exceptions import InvalidParameterException, RepeatedParameterException 4 | 5 | DIST_TO_PARAM_NAMES = { 6 | "AsymmetricLaplace": ["kappa", "mu", "b", "q"], 7 | "Bernoulli": ["p", "logit_p"], 8 | "Beta": ["alpha", "beta", "mu", "sigma", "nu"], 9 | "BetaBinomial": ["alpha", "beta", "n"], 10 | "BetaScaled": ["alpha", "beta", "lower", "upper"], 11 | "Binomial": ["n", "p"], 12 | "Categorical": ["p", "logit_p"], 13 | "Cauchy": ["alpha", "beta"], 14 | "ChiSquared": ["nu"], 15 | "Dirichlet": ["alpha"], 16 | "DiscreteUniform": ["lower", "upper"], 17 | "DiscreteWeibull": ["q", "beta"], 18 | "ExGaussian": ["mu", "sigma", "nu"], 19 | "Exponential": ["lam", "beta"], 20 | "Gamma": ["alpha", "beta", "mu", "sigma"], 21 | "Geometric": ["p"], 22 | "Gumbel": ["mu", "beta"], 23 | "HalfCauchy": ["beta"], 24 | "HalfNormal": ["sigma", "tau"], 25 | "HalfStudentT": ["nu", "sigma", "lam"], 26 | "HyperGeometric": ["N", "k", "n"], 27 | "InverseGamma": ["alpha", "beta", "mu", "sigma"], 28 | "Kumaraswamy": ["a", "b"], 29 | "Laplace": ["mu", "b"], 30 | "LogLogistic": ["alpha", "beta"], 31 | "LogNormal": ["mu", "sigma"], 32 | "Logistic": ["mu", "s"], 33 | "LogitNormal": ["mu", "sigma", "tau"], 34 | "Moyal": ["mu", "sigma"], 35 | "MvNormal": ["mu", "cov", "tau"], 36 | "NegativeBinomial": ["mu", "alpha", "p", "n"], 37 | "Normal": ["mu", "sigma", "tau"], 38 | "Pareto": ["alpha", "m"], 39 | "Poisson": ["mu"], 40 | "Rice": ["nu", "sigma", "b"], 41 | "SkewNormal": ["mu", "sigma", "alpha", "tau"], 42 | "SkewStudentT": ["mu", "sigma", "a", "b", "lam"], 43 | "StudentT": ["nu", "mu", "sigma", "lam"], 44 | "Triangular": ["lower", "c", "upper"], 45 | "TruncatedNormal": ["mu", "sigma", "lower", "upper"], 46 | "Uniform": ["lower", "upper"], 47 | "VonMises": ["mu", "kappa"], 48 | "Wald": ["mu", "lam", "phi"], 49 | "Weibull": ["alpha", "beta"], 50 | "ZeroInflatedBinomial": ["psi", "n", "p"], 51 | "ZeroInflatedNegativeBinomial": ["psi", "mu", "alpha", "p", "n"], 52 | "ZeroInflatedPoisson": ["psi", "mu"], 53 | } 54 | 55 | WRAPPER_TO_ARGS = { 56 | "maxent": ["lower", "upper", "mass"], 57 | "Censored": ["lower", "upper"], 58 | "Truncated": ["lower", "upper"], 59 | "Hurdle": ["psi"], 60 | } 61 | 62 | 63 | PRELIZ_DISTS = list(DIST_TO_PARAM_NAMES.keys()) 64 | PRELIZ_DIST_WRAPPERS = list(WRAPPER_TO_ARGS.keys()) 65 | 66 | 67 | def evaluate_expression(parsed_expr): 68 | if isinstance(parsed_expr, int | float): 69 | return float(parsed_expr) 70 | elif not parsed_expr: 71 | return None 72 | elif isinstance(parsed_expr, pp.ParseResults): 73 | parsed_expr = parsed_expr.as_list() 74 | if len(parsed_expr) == 1 and isinstance(parsed_expr[0], list): 75 | parsed_expr = parsed_expr[0] 76 | expr_str = "".join(map(str, parsed_expr)) 77 | return eval(expr_str, {"__builtins__": None}, {}) 78 | return parsed_expr 79 | 80 | 81 | def result_to_dict(parsed_tokens, dist_name, valid_params): 82 | if not parsed_tokens: 83 | return {} 84 | 85 | parsed_tokens = [x for x in parsed_tokens.as_list() if x is not None] 86 | if len(parsed_tokens) == 0: 87 | return {} 88 | 89 | res = {} 90 | 91 | for param_name, param_value in parsed_tokens: 92 | if param_name in res: 93 | raise RepeatedParameterException(dist_name, param_name) 94 | if param_name not in valid_params: 95 | raise InvalidParameterException(dist_name, param_name, valid_params) 96 | res[param_name] = param_value 97 | 98 | return res 99 | 100 | 101 | def process_initial_value(initial_value): 102 | if isinstance(initial_value, float | int | None): 103 | return initial_value 104 | 105 | return initial_value.as_list() 106 | 107 | 108 | WRAPPER_FUNCS = pp.MatchFirst([pp.Keyword(wrapper) for wrapper in PRELIZ_DIST_WRAPPERS]) 109 | DISTRIBUTION_ID = pp.MatchFirst([pp.Keyword(dist) for dist in PRELIZ_DISTS]) 110 | 111 | VARIABLE_ID = pp.Word(pp.alphas, pp.alphanums + "_") 112 | 113 | EQUALS = pp.Literal("=").suppress() 114 | LPAREN = pp.Literal("(").suppress() 115 | RPAREN = pp.Literal(")").suppress() 116 | COMMA = pp.Literal(",").suppress() 117 | 118 | NUMBER = pp.pyparsing_common.number 119 | NUMBER_EXPR = pp.infixNotation( 120 | NUMBER, 121 | [ 122 | (pp.Literal("/"), 2, pp.opAssoc.LEFT), 123 | (pp.Literal("*"), 2, pp.opAssoc.LEFT), 124 | (pp.Literal("+"), 2, pp.opAssoc.LEFT), 125 | (pp.Literal("-"), 2, pp.opAssoc.LEFT), 126 | ], 127 | ) 128 | 129 | VALUE = NUMBER_EXPR | VARIABLE_ID 130 | 131 | ARG_NAME = pp.Word(pp.alphas, pp.alphanums + "_") 132 | KEY_VALUE_PAIR = pp.Group(ARG_NAME + EQUALS + VALUE) 133 | 134 | KWARG_LIST = pp.Optional(pp.delimitedList(KEY_VALUE_PAIR, delim=COMMA), default=None) 135 | 136 | 137 | DIST = DISTRIBUTION_ID("dist_name") + LPAREN + KWARG_LIST("dist_kwargs") + RPAREN 138 | INITIAL_VALUE = EQUALS + NUMBER_EXPR("initial_value") 139 | 140 | wrapped_distribution = ( 141 | WRAPPER_FUNCS("wrapper_name") 142 | + LPAREN 143 | + DIST 144 | + pp.Optional(COMMA + KWARG_LIST("wrapper_kwargs")) 145 | + RPAREN 146 | ) 147 | 148 | dist_syntax = ( 149 | (wrapped_distribution | DIST) + pp.Optional(INITIAL_VALUE) + pp.StringEnd() 150 | ) 151 | 152 | 153 | def dist_parse_action(tokens): 154 | res = { 155 | "dist_name": tokens["dist_name"], 156 | "wrapper_name": tokens.get("wrapper_name", None), 157 | "initial_value": process_initial_value(tokens.get("initial_value", None)), 158 | } 159 | 160 | dist_name = res["dist_name"] 161 | wrapper_name = res["wrapper_name"] 162 | 163 | res["dist_kwargs"] = result_to_dict( 164 | tokens["dist_kwargs"], dist_name, DIST_TO_PARAM_NAMES[dist_name] 165 | ) 166 | res["wrapper_kwargs"] = result_to_dict( 167 | tokens.get("wrapper_kwargs"), 168 | wrapper_name, 169 | WRAPPER_TO_ARGS.get(wrapper_name, []), 170 | ) 171 | 172 | return res 173 | 174 | 175 | dist_syntax.add_parse_action(dist_parse_action) 176 | 177 | 178 | __all__ = ["PRELIZ_DISTS", "PRELIZ_DIST_WRAPPERS", "dist_syntax", "evaluate_expression"] 179 | -------------------------------------------------------------------------------- /gEconpy/parser/html.py: -------------------------------------------------------------------------------- 1 | from typing import TYPE_CHECKING 2 | 3 | from IPython.core.display_functions import display 4 | from IPython.display import HTML 5 | 6 | from gEconpy.parser.file_loaders import gcn_to_block_dict 7 | 8 | if TYPE_CHECKING: 9 | from gEconpy.model.block import Block 10 | 11 | 12 | def get_css() -> str: 13 | """ 14 | Return a CSS string to style the generated HTML. 15 | The style is inspired by the xarray HTML representation. 16 | Each block is rendered in a unified container with an unbroken background, 17 | and the whole block is collapsible. 18 | """ 19 | css = r""" 20 | 103 | """ 104 | return css 105 | 106 | 107 | def generate_html(blocks: list["Block"]) -> HTML: 108 | """ 109 | Represent a model in HTML 110 | 111 | Parameters 112 | ---------- 113 | blocks : list[Block] 114 | List of blocks to represent 115 | """ 116 | html_parts = [] 117 | html_parts.append(""" 118 | 127 | """) 128 | html_parts.append(get_css()) 129 | 130 | html_parts.append( 131 | "
" 132 | ) 133 | html_parts.append("
") 134 | for block in blocks: 135 | html_parts.append(block.__html_repr__()) 136 | html_parts.append("
") 137 | html_parts.append("
") 138 | 139 | html_parts.append(""" 140 | 150 | """) 151 | 152 | final_html = "\n".join(html_parts) 153 | return HTML(final_html) 154 | 155 | 156 | def print_gcn_file(gcn_path: str) -> None: 157 | """ 158 | Display a model in HTML 159 | 160 | Parameters 161 | ---------- 162 | gcn_file : str 163 | Path to the GCN file 164 | """ 165 | outputs = gcn_to_block_dict(gcn_path, simplify_blocks=False, include_ss_block=True) 166 | block_dict, assumptions, options, try_reduce, ss_solution_dict, prior_info = outputs 167 | blocks = list(block_dict.values()) 168 | 169 | # TODO: Do stuff with the other outputs 170 | html = generate_html(blocks) 171 | display(html) 172 | -------------------------------------------------------------------------------- /gEconpy/parser/validation.py: -------------------------------------------------------------------------------- 1 | from gEconpy.exceptions import InvalidComponentNameException 2 | from gEconpy.parser.constants import BLOCK_COMPONENTS 3 | 4 | 5 | def block_is_empty(block: str) -> bool: 6 | """ 7 | Check whether a model block is empty, i.e. contains no flags, variables, or equations. 8 | 9 | Parameters 10 | ---------- 11 | block : str 12 | Raw text of a model block. 13 | 14 | Returns 15 | ------- 16 | bool 17 | Whether the block is empty or not. 18 | """ 19 | 20 | return block.strip() == "{ };" 21 | 22 | 23 | def validate_key(key: str, block_name: str) -> None: 24 | """ 25 | Check that the component name matches something in the list of valid block components. 26 | 27 | The R implementation of gEcon only allows the names in BLOCK_COMPONENTS to be used inside model blocks. 28 | This function checks that a component name matches something in that list, and raises an error if not. 29 | 30 | Parameters 31 | ---------- 32 | block_name : str 33 | The name of the block. 34 | key : str 35 | A block sub-component name. 36 | 37 | Returns 38 | ------- 39 | None 40 | 41 | Raises 42 | ------ 43 | InvalidComponentNameException 44 | If the component name is invalid. 45 | 46 | # TODO: Allow arbitrary component names? Is there any need to? 47 | """ 48 | if key.upper() not in BLOCK_COMPONENTS: 49 | valid_names = ", ".join(BLOCK_COMPONENTS) 50 | error = f"Valid sub-block names are: {valid_names}\n" 51 | error += f"Found: {key} in block {block_name}" 52 | 53 | raise InvalidComponentNameException( 54 | component_name=key, block_name=block_name, message=error 55 | ) 56 | 57 | 58 | def jaccard_distance(s: str, d: str) -> float: 59 | """ 60 | Calculate the Jaccard distance between two strings. 61 | 62 | The Jaccard distance is defined as the size of the intersection of two sets divided by the size of their union. 63 | For example, the Jaccard distance between the sets {"C", "A", "T"} and {"C", "U", "T"} is 1/2 because the 64 | intersection of these two sets is {"C", "T"} (of size 2) and the union is {"C", "A", "T", "U"} (of size 4). 65 | Therefore, the Jaccard distance is 2/4 = 1/2. 66 | 67 | Parameters 68 | ---------- 69 | s : str 70 | The first string. 71 | d : str 72 | The second string. 73 | 74 | Returns 75 | ------- 76 | float 77 | The Jaccard distance between the two strings. 78 | """ 79 | 80 | s = set(s) 81 | d = set(d) 82 | union = len(s.union(d)) 83 | intersection = len(s.intersection(d)) 84 | 85 | return intersection / union 86 | 87 | 88 | def elementwise_jaccard_distance(s: str, elements: list[str]) -> list[float]: 89 | """ 90 | Calculate the Jaccard distance between a string and each element in a list of strings. 91 | 92 | Parameters 93 | ---------- 94 | s : str 95 | The string to compare against. 96 | elements : list of str 97 | The list of strings to compare to `s`. 98 | 99 | Returns 100 | ------- 101 | list of float 102 | A list of the Jaccard distances between `s` and each element in `l`. 103 | """ 104 | return [jaccard_distance(s, element) for element in elements] 105 | 106 | 107 | def find_typos_and_guesses( 108 | user_inputs: list[str], valid_inputs: list[str], match_threshold: float = 0.8 109 | ) -> tuple[str | None, str | None]: 110 | """ 111 | Find the best matching suggestion from a list of valid inputs for a list of invalid user inputs. 112 | 113 | Parameters 114 | ---------- 115 | user_inputs : list of str 116 | The list of invalid user inputs. 117 | valid_inputs : list of str 118 | The list of valid inputs. 119 | match_threshold : float, optional 120 | The minimum Jaccard distance required to consider a user input a typo. Default is 0.8. 121 | 122 | Returns 123 | ------- 124 | tuple of (str or None, str or None) 125 | A tuple containing the best matching valid input and the user input that may be a typo, if they are above the 126 | match threshold. If no user input is above the threshold, both elements of the tuple will be None. 127 | """ 128 | 129 | # TODO: Tune match_threshold 130 | 131 | best_guess = max( 132 | valid_inputs, key=lambda x: elementwise_jaccard_distance(x, user_inputs) 133 | ) 134 | maybe_typo = max( 135 | user_inputs, key=lambda x: elementwise_jaccard_distance(x, valid_inputs) 136 | ) 137 | 138 | if jaccard_distance(best_guess, maybe_typo) < match_threshold: 139 | return None, None 140 | 141 | return best_guess, maybe_typo 142 | -------------------------------------------------------------------------------- /gEconpy/solvers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/gEconpy/solvers/__init__.py -------------------------------------------------------------------------------- /gEconpy/solvers/shared.py: -------------------------------------------------------------------------------- 1 | import pytensor.tensor as pt 2 | 3 | from pytensor.tensor import TensorVariable 4 | 5 | 6 | def stabilize(x, jitter=1e-16): 7 | return x + jitter * pt.eye(x.shape[0]) 8 | 9 | 10 | def o1_policy_function_adjoints( 11 | A: TensorVariable, 12 | B: TensorVariable, 13 | C: TensorVariable, 14 | T: TensorVariable, 15 | T_bar: TensorVariable, 16 | ) -> list[TensorVariable, TensorVariable, TensorVariable]: 17 | """ 18 | Compute the adjoints of the inputs to the equation: 19 | 20 | ..math:: 21 | 22 | A + BT + CTT = 0 23 | 24 | Which is the matrix quadratic equation associated with the first order approximation to a DSGE policy function. 25 | 26 | Parameters 27 | ---------- 28 | A: TensorVariable 29 | Matrix of partial derivatives with respect to variables at t-1, evaluated at the steady-state 30 | B: TensorVariable 31 | Matrix of partial derivatives with respect to variables at t, evaluated at the steady-state 32 | C: TensorVariable 33 | Matrix of partial derivatives with respect to variables at t+1, evaluated at the steady-state 34 | T: TensorVariable 35 | T_bar: TensorVariable 36 | Backward sensitivity of a scalar loss function with respect to the solved policy function T 37 | 38 | Returns 39 | ------- 40 | adjoints: list of TensorVariable 41 | A_bar: TensorVariable 42 | Adjoint of A 43 | B_bar: TensorVariable 44 | Adjoint of B 45 | C_bar: TensorVariable 46 | Adjoint of C 47 | """ 48 | vec_T_bar = T_bar.T.ravel() 49 | 50 | n = A.shape[0] 51 | 52 | # Compute matrix of lagrange multipliers S 53 | eye = pt.eye(n) 54 | M1 = pt.linalg.kron(T, C.T) 55 | M2 = pt.linalg.kron(eye, T.T @ C.T) 56 | M3 = pt.linalg.kron(eye, B.T) 57 | 58 | vec_S = pt.linalg.solve( 59 | stabilize(M1 + M2 + M3), -vec_T_bar, assume_a="gen", check_finite=False 60 | ) 61 | S = vec_S.reshape((n, n)).T 62 | 63 | # With S, compute adjoints of the inputs 64 | A_bar = S 65 | B_bar = S @ T.T 66 | C_bar = S @ T.T @ T.T 67 | 68 | return [A_bar, B_bar, C_bar] 69 | 70 | 71 | def pt_compute_selection_matrix(B, C, D, T): 72 | return -pt.linalg.solve( 73 | C @ T + B, D.astype(T.dtype), assume_a="gen", check_finite=False 74 | ) 75 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "versioneer[toml]"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | 6 | [project] 7 | name = "gEconpy" 8 | dynamic = ['version'] 9 | requires-python = ">=3.11" 10 | authors = [{name="Jesse Grabowski", email='jessegrabowski@gmail.com'}] 11 | description = "A package for solving, estimating, and analyzing DSGE models" 12 | readme = 'README.md' 13 | license = { file = 'LICENSE.txt'} 14 | classifiers = [ 15 | "Development Status :: 2 - Pre-Alpha", 16 | "Intended Audience :: Science/Research", 17 | "Programming Language :: Python", 18 | "Topic :: Scientific/Engineering", 19 | "Operating System :: Microsoft :: Windows", 20 | "Operating System :: POSIX", 21 | "Operating System :: Unix", 22 | "Operating System :: MacOS", 23 | "Programming Language :: Python :: 3", 24 | "Programming Language :: Python :: 3.10", 25 | "Programming Language :: Python :: 3.11", 26 | "Programming Language :: Python :: 3.12", 27 | ] 28 | 29 | keywords = [ 30 | "dynamic stochastic general equlibrium", 31 | "economics", 32 | "macroeconomics", 33 | "numerical", 34 | "simulation", 35 | "autodiff", 36 | "bayesian statistics" 37 | ] 38 | 39 | 40 | dependencies = [ 41 | "matplotlib", 42 | "numba", 43 | "numpy", 44 | "pandas", 45 | "pymc", 46 | "pymc_extras", 47 | "preliz", 48 | "pyparsing", 49 | "pytensor", 50 | "scipy", 51 | "setuptools", 52 | "sympy<1.13", 53 | "sympytensor", 54 | "ipython", 55 | "xarray", 56 | ] 57 | 58 | [project.optional-dependencies] 59 | dev = [ 60 | "pre-commit", 61 | "pytest", 62 | "pytest-cov", 63 | "versioneer", 64 | "numdifftools" 65 | ] 66 | 67 | docs = [ 68 | "ipython", 69 | "jupyter-sphinx", 70 | "myst-nb", 71 | "numpydoc", 72 | "pre-commit", 73 | "sphinx>=5", 74 | "sphinx-copybutton", 75 | "sphinx-design", 76 | "sphinx-notfound-page", 77 | "sphinx-sitemap", 78 | "sphinx-codeautolink", 79 | "sphinxcontrib-bibtex", 80 | "pydata-sphinx-theme", 81 | "watermark", 82 | ] 83 | 84 | 85 | [tool.versioneer] 86 | VCS = "git" 87 | style = "pep440" 88 | versionfile_source = "gEconpy/_version.py" 89 | versionfile_build = "gEconpy/_version.py" 90 | tag_prefix = 'v' 91 | 92 | 93 | [tool.pytest.ini_options] 94 | minversion = "6.0" 95 | xfail_strict=true 96 | log_cli=true 97 | log_cli_level="INFO" 98 | filterwarnings = [ 99 | "error", 100 | "ignore::DeprecationWarning", 101 | "ignore::RuntimeWarning"] 102 | 103 | 104 | [tool.ruff.lint] 105 | select = ["D", "E", "F", "I", "UP", "W", "RUF"] 106 | ignore = [ 107 | "E501", # Line length 108 | "E741", # Ambiguous variable name 109 | "RUF001", # String contains ambiguous character (such as Greek letters) 110 | "RUF002", # Docstring contains ambiguous character (such as Greek letters) 111 | "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` 112 | "D100", 113 | "D101", 114 | "D102", 115 | "D103", 116 | "D104", 117 | "D105", 118 | "D107", 119 | "D200", 120 | "D202", 121 | "D203", 122 | "D204", 123 | "D205", 124 | "D209", 125 | "D212", 126 | "D213", 127 | "D301", 128 | "D400", 129 | "D401", 130 | "D403", 131 | "D413", 132 | "D415", 133 | "D417", 134 | ] 135 | 136 | [tool.ruff.lint.isort] 137 | lines-between-types = 1 138 | 139 | [tool.ruff.lint.per-file-ignores] 140 | 'tests/*.py' = [ 141 | 'F401', # Unused import warning for test files -- this check removes imports of fixtures 142 | 'F811', # Redefine while unused -- this check fails on imported fixtures 143 | 'F841', # Unused variable warning for test files -- common in pymc model declarations 144 | 'D106' # Missing docstring for public method -- unittest test subclasses don't need docstrings 145 | ] 146 | 'docs/source/examples/case_study/*.ipynb' = [ 147 | 'F821' # Notebooks uses direct assignment to globals, so ruff thinks variables are not declared 148 | ] 149 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import versioneer 2 | 3 | from setuptools import find_packages, setup 4 | from setuptools.dist import Distribution 5 | 6 | dist = Distribution() 7 | dist.parse_config_files() 8 | 9 | 10 | NAME: str = dist.get_name() # type: ignore 11 | 12 | 13 | if __name__ == "__main__": 14 | setup( 15 | name=NAME, 16 | version=versioneer.get_version(), 17 | cmdclass=versioneer.get_cmdclass(), 18 | packages=find_packages(exclude=["tests*"]), 19 | ) 20 | -------------------------------------------------------------------------------- /sphinxext/generate_gallery.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sphinx plugin to run generate a gallery for notebooks 3 | 4 | Modified from the pymc project, whihch modified the seaborn project, which modified the mpld3 project. 5 | """ 6 | 7 | import base64 8 | import json 9 | import os 10 | import shutil 11 | 12 | from glob import glob 13 | 14 | import matplotlib 15 | 16 | matplotlib.use("Agg") 17 | import matplotlib.pyplot as plt 18 | import sphinx 19 | 20 | from matplotlib import image 21 | from pathlib import Path 22 | 23 | logger = sphinx.util.logging.getLogger(__name__) 24 | 25 | DOC_SRC = Path(__file__).resolve().parent.parent 26 | 27 | DEFAULT_IMG_LOC = None 28 | external_nbs = {} 29 | 30 | HEAD = """ 31 | Example Gallery 32 | =============== 33 | 34 | .. toctree:: 35 | :hidden: 36 | 37 | """ 38 | 39 | SECTION_TEMPLATE = """ 40 | .. _{section_id}: 41 | 42 | {section_title} 43 | {underlines} 44 | 45 | .. grid:: 1 2 3 3 46 | :gutter: 4 47 | 48 | """ 49 | 50 | ITEM_TEMPLATE = """ 51 | .. grid-item-card:: :doc:`{doc_name}` 52 | :img-top: {image} 53 | :link: {doc_reference} 54 | :link-type: {link_type} 55 | :shadow: none 56 | """ 57 | 58 | folder_title_map = { 59 | "introductory": "Introductory", 60 | "estimation": "Estimation", 61 | "case_study": "Case Studies", 62 | } 63 | 64 | 65 | def create_thumbnail(infile, width=275, height=275, cx=0.5, cy=0.5, border=4): 66 | """Overwrites `infile` with a new file of the given size""" 67 | im = image.imread(infile) 68 | rows, cols = im.shape[:2] 69 | size = min(rows, cols) 70 | if size == cols: 71 | xslice = slice(0, size) 72 | ymin = min(max(0, int(cx * rows - size // 2)), rows - size) 73 | yslice = slice(ymin, ymin + size) 74 | else: 75 | yslice = slice(0, size) 76 | xmin = min(max(0, int(cx * cols - size // 2)), cols - size) 77 | xslice = slice(xmin, xmin + size) 78 | thumb = im[yslice, xslice] 79 | thumb[:border, :, :3] = thumb[-border:, :, :3] = 0 80 | thumb[:, :border, :3] = thumb[:, -border:, :3] = 0 81 | 82 | dpi = 100 83 | fig = plt.figure(figsize=(width / dpi, height / dpi), dpi=dpi) 84 | 85 | ax = fig.add_axes([0, 0, 1, 1], aspect="auto", frameon=False, xticks=[], yticks=[]) 86 | ax.imshow(thumb, aspect="auto", resample=True, interpolation="bilinear") 87 | fig.savefig(infile, dpi=dpi) 88 | plt.close(fig) 89 | return fig 90 | 91 | 92 | class NotebookGenerator: 93 | """Tools for generating an example page from a file""" 94 | 95 | def __init__(self, filename, root_dir, folder): 96 | self.folder = folder 97 | 98 | self.basename = Path(filename).name 99 | self.stripped_name = Path(filename).stem 100 | self.image_dir = Path(root_dir) / "source" / "_thumbnails" / folder 101 | self.png_path = self.image_dir / f"{self.stripped_name}.png" 102 | 103 | with filename.open(encoding="utf-8") as fid: 104 | self.json_source = json.load(fid) 105 | self.default_image_loc = DEFAULT_IMG_LOC 106 | 107 | def extract_preview_pic(self): 108 | """By default, just uses the last image in the notebook.""" 109 | pic = None 110 | for cell in self.json_source["cells"]: 111 | for output in cell.get("outputs", []): 112 | if "image/png" in output.get("data", []): 113 | pic = output["data"]["image/png"] 114 | if pic is not None: 115 | return base64.b64decode(pic) 116 | return None 117 | 118 | def gen_previews(self): 119 | preview = self.extract_preview_pic() 120 | if preview is not None: 121 | with self.png_path.open("wb") as buff: 122 | buff.write(preview) 123 | else: 124 | logger.warning( 125 | f"Didn't find any pictures in {self.basename}", 126 | type="thumbnail_extractor", 127 | ) 128 | shutil.copy(self.default_image_loc, self.png_path) 129 | create_thumbnail(self.png_path) 130 | 131 | 132 | def main(app): 133 | logger.info("Starting thumbnail extractor.") 134 | 135 | os.chdir(app.builder.srcdir) 136 | working_dir = Path.cwd() 137 | 138 | logger.info(f"Current working directory: {working_dir}") 139 | 140 | file = [HEAD] 141 | 142 | for folder, title in folder_title_map.items(): 143 | file.append( 144 | SECTION_TEMPLATE.format( 145 | section_title=title, section_id=folder, underlines="-" * len(title) 146 | ) 147 | ) 148 | 149 | thumbnail_dir = working_dir / "_thumbnails" / folder 150 | if not thumbnail_dir.exists(): 151 | Path.mkdir(thumbnail_dir, parents=True) 152 | 153 | if folder in external_nbs.keys(): 154 | file += [ 155 | ITEM_TEMPLATE.format( 156 | doc_name=descr["doc_name"], 157 | image=descr["image"], 158 | doc_reference=descr["doc_reference"], 159 | link_type=descr["link_type"], 160 | ) 161 | for descr in external_nbs[folder] 162 | ] 163 | 164 | nb_paths = sorted(Path("examples", folder).glob("*.ipynb")) 165 | 166 | for nb_path in nb_paths: 167 | nbg = NotebookGenerator( 168 | filename=nb_path, root_dir=Path(".."), folder=folder 169 | ) 170 | nbg.gen_previews() 171 | 172 | file.append( 173 | ITEM_TEMPLATE.format( 174 | doc_name=Path(folder) / nbg.stripped_name, 175 | image="/" + str(nbg.png_path), 176 | doc_reference=Path(folder) / nbg.stripped_name, 177 | link_type="doc", 178 | ) 179 | ) 180 | 181 | with Path("examples", "gallery.rst").open("w", encoding="utf-8") as f: 182 | f.write("\n".join(file)) 183 | 184 | os.chdir(working_dir) 185 | 186 | 187 | def setup(app): 188 | app.connect("builder-inited", main) 189 | -------------------------------------------------------------------------------- /tests/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/.DS_Store -------------------------------------------------------------------------------- /tests/Test Answer Strings/test_block_deletion.txt: -------------------------------------------------------------------------------- 1 | options { output logfile = TRUE ; output LaTeX = TRUE ; output LaTeX landscape = TRUE ; }; 2 | -------------------------------------------------------------------------------- /tests/Test Answer Strings/test_parse_gcn.txt: -------------------------------------------------------------------------------- 1 | block HOUSEHOLD { definitions { u[] = log ( C[] ) - log ( L[] ) ; }; objective { U[] = u[] + beta * E[] [ U[1] ] ; }; controls { C[], L[] ; }; constraints { C[] = w[] * L[] ; }; calibration { beta = 0.99 ; }; }; 2 | -------------------------------------------------------------------------------- /tests/Test Answer Strings/test_split_gcn_by_blocks.txt: -------------------------------------------------------------------------------- 1 | { definitions { u[] = ( C[] ^ ( 1 - gamma ) - 1 ) / ( 1 - gamma ) ; }; controls { C[], K[] ; }; objective { U[] = u[] + beta * E[] [ U[1] ] ; }; constraints { C[] + K[] - ( 1 - delta ) * K[-1] = A[] * K[-1] ^ alpha : lambda[] ; }; identities { log ( A[] ) = rho * log ( A[-1] ) + epsilon[] ; }; shocks { epsilon[] ; }; calibration { alpha = 0.4 ; beta = 0.99 ; delta = 0.02 ; rho = 0.95 ; gamma = 1.5 ; }; }; 2 | -------------------------------------------------------------------------------- /tests/Test GCNs/basic_rbc.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | output logfile = FALSE; 4 | output LaTeX = FALSE; 5 | }; 6 | 7 | tryreduce 8 | { 9 | U[], TC[]; 10 | }; 11 | 12 | block HOUSEHOLD 13 | { 14 | definitions 15 | { 16 | u[] = C[] ^ (1 - sigma_C) / (1 - sigma_C) - L[] ^ (1 + sigma_L) / (1 + sigma_L); 17 | }; 18 | 19 | controls 20 | { 21 | C[], L[], I[], K[]; 22 | }; 23 | 24 | objective 25 | { 26 | U[] = u[] + beta * E[][U[1]]; 27 | }; 28 | 29 | constraints 30 | { 31 | C[] + I[] = r[] * K[-1] + w[] * L[] : lambda[]; 32 | K[] = (1 - delta) * K[-1] + I[]; 33 | }; 34 | 35 | calibration 36 | { 37 | beta = 0.99; 38 | delta = 0.02; 39 | sigma_C = 1.5; 40 | sigma_L = 2.0; 41 | }; 42 | }; 43 | 44 | block FIRM 45 | { 46 | controls 47 | { 48 | K[-1], L[]; 49 | }; 50 | 51 | objective 52 | { 53 | TC[] = -(r[] * K[-1] + w[] * L[]); 54 | }; 55 | 56 | constraints 57 | { 58 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : mc[]; 59 | }; 60 | 61 | identities 62 | { 63 | # Perfect competition 64 | mc[] = 1; 65 | }; 66 | 67 | calibration 68 | { 69 | alpha = 0.35; 70 | }; 71 | }; 72 | 73 | block TECHNOLOGY_SHOCKS 74 | { 75 | identities 76 | { 77 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 78 | }; 79 | 80 | shocks 81 | { 82 | epsilon_A[]; 83 | }; 84 | 85 | calibration 86 | { 87 | rho_A = 0.95; 88 | }; 89 | }; 90 | -------------------------------------------------------------------------------- /tests/Test GCNs/conflicting_assumptions.gcn: -------------------------------------------------------------------------------- 1 | assumptions 2 | { 3 | imaginary 4 | { 5 | TC[]; 6 | }; 7 | }; 8 | 9 | block BLOCK 10 | { 11 | identities 12 | { 13 | TC[] = -1; 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /tests/Test GCNs/full_nk_no_ss.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | output logfile = TRUE; 4 | output LaTeX = TRUE; 5 | output LaTeX landscape = TRUE; 6 | }; 7 | 8 | assumptions 9 | { 10 | negative 11 | { 12 | TC[]; 13 | }; 14 | 15 | positive 16 | { 17 | shock_technology[], shock_preference[], pi[], pi_star[], pi_obj[], r[], r_G[], mc[], w[], w_star[], 18 | Y[], C[], I[], K[], L[], 19 | delta, beta, sigma_C, sigma_L, gamma_I, phi_H; 20 | }; 21 | }; 22 | 23 | block HOUSEHOLD 24 | { 25 | definitions 26 | { 27 | u[] = shock_preference[] * ( 28 | (C[] - phi_H * C[-1]) ^ (1 - sigma_C) / (1 - sigma_C) - 29 | L[] ^ (1 + sigma_L) / (1 + sigma_L)); 30 | }; 31 | controls 32 | { 33 | C[], I[], K[], B[]; 34 | }; 35 | 36 | objective 37 | { 38 | U[] = u[] + beta * E[][U[1]]; 39 | }; 40 | 41 | constraints 42 | { 43 | C[] + I[] + B[] / r_G[] = 44 | r[] * K[-1] + 45 | w[] * L[] + 46 | B[-1] / pi[] + 47 | Div[] : lambda[]; 48 | 49 | K[] = (1 - delta) * K[-1] + 50 | I[] * (1 - gamma_I / 2 * (I[] / I[-1] - 1) ^ 2) : q[]; 51 | }; 52 | 53 | calibration 54 | { 55 | delta = 0.025; 56 | beta = 0.99; 57 | 58 | sigma_C = 2; 59 | sigma_L = 1.5; 60 | 61 | gamma_I = 10; 62 | phi_H = 0.5; 63 | }; 64 | }; 65 | 66 | block WAGE_SETTING 67 | { 68 | definitions 69 | { 70 | L_d_star[] = (w[] / w_star[]) ^ ((1 + psi_w) / psi_w) * L[]; 71 | }; 72 | 73 | identities 74 | { 75 | LHS_w[] = RHS_w[]; 76 | 77 | LHS_w[] = 1 / (1 + psi_w) * w_star[] * lambda[] * L_d_star[] + 78 | beta * eta_w * E[][ 79 | pi[1] * (w_star[1] / w_star[]) ^ (1 / psi_w) * LHS_w[1] 80 | ]; 81 | 82 | RHS_w[] = shock_preference[] * L_d_star[] ^ (1 + sigma_L) + 83 | beta * eta_w * E[][ 84 | (pi[1] * w_star[1] / w_star[]) ^ ((1 + psi_w) * (1 + sigma_L) / psi_w) * 85 | RHS_w[1] 86 | ]; 87 | 88 | }; 89 | 90 | calibration 91 | { 92 | psi_w = 0.782; # Elasticity of substitution between forms of labor 93 | eta_w = 0.75; # Probability of not receiving the update signal 94 | }; 95 | }; 96 | 97 | block WAGE_EVOLUTION 98 | { 99 | identities 100 | { 101 | 1 = eta_w * (pi[] * w[] / w[-1]) ^ (1 / psi_w) + 102 | (1 - eta_w) * (w[] / w_star[]) ^ (1 / psi_w); 103 | }; 104 | }; 105 | 106 | 107 | block PREFERENCE_SHOCKS 108 | { 109 | identities 110 | { 111 | log(shock_preference[]) = rho_preference * log(shock_preference[-1]) + epsilon_preference[]; 112 | }; 113 | 114 | shocks 115 | { 116 | epsilon_preference[]; 117 | }; 118 | 119 | calibration 120 | { 121 | rho_preference = 0.95; 122 | }; 123 | }; 124 | 125 | 126 | block FIRM 127 | { 128 | controls 129 | { 130 | K[-1], L[]; 131 | }; 132 | 133 | objective 134 | { 135 | TC[] = -(L[] * w[] + K[-1] * r[]); 136 | }; 137 | 138 | constraints 139 | { 140 | Y[] = shock_technology[] * K[-1] ^ alpha * 141 | L[] ^ (1 - alpha) : mc[]; 142 | }; 143 | 144 | identities 145 | { 146 | Div[] = Y[] + TC[]; 147 | }; 148 | 149 | calibration 150 | { 151 | alpha = 0.35; 152 | }; 153 | }; 154 | 155 | 156 | block TECHNOLOGY_SHOCKS 157 | { 158 | identities 159 | { 160 | log(shock_technology[]) = rho_technology * log(shock_technology[-1]) + epsilon_Y[]; 161 | }; 162 | shocks 163 | { 164 | epsilon_Y[]; 165 | }; 166 | calibration 167 | { 168 | rho_technology = 0.95; 169 | }; 170 | }; 171 | 172 | 173 | block FIRM_PRICE_SETTING_PROBLEM 174 | { 175 | identities 176 | { 177 | LHS[] = (1 + psi_p) * RHS[]; 178 | 179 | LHS[] = lambda[] * Y[] * pi_star[] + 180 | beta * eta_p * E[][ 181 | pi_star[] / pi_star[1] * pi[1] ^ (1 / psi_p) * LHS[1]]; 182 | 183 | RHS[] = lambda[] * mc[] * Y[] + 184 | beta * eta_p * E[][ 185 | pi[1] ^ ((1 + psi_p) / psi_p) * RHS[1]]; 186 | }; 187 | 188 | calibration 189 | { 190 | psi_p = 0.6; 191 | eta_p = 0.75; 192 | }; 193 | }; 194 | 195 | 196 | block PRICE_EVOLUTION 197 | { 198 | identities 199 | { 200 | 1 = eta_p * pi[] ^ (1 / psi_p) + 201 | (1 - eta_p) * pi_star[] ^ (-1 / psi_p); 202 | }; 203 | }; 204 | 205 | 206 | block MONETARY_POLICY 207 | { 208 | identities 209 | { 210 | log(r_G[] / r_G[ss]) = gamma_R * log(r_G[-1] / r_G[ss]) + 211 | (1 - gamma_R) * log(pi_obj[]) + 212 | (1 - gamma_R) * gamma_pi * log(pi[] / pi[ss] - log(pi_obj[])) + 213 | (1 - gamma_R) * gamma_Y * log(Y[] / Y[-1]) + 214 | epsilon_R[]; 215 | 216 | log(pi_obj[]) = (1 - rho_pi_dot) * log(phi_pi_obj) + 217 | rho_pi_dot * log(pi_obj[-1]) + epsilon_pi[]; 218 | }; 219 | 220 | shocks 221 | { 222 | epsilon_R[], epsilon_pi[]; 223 | }; 224 | 225 | 226 | calibration 227 | { 228 | gamma_R = 0.9; 229 | gamma_pi = 1.5; 230 | gamma_Y = 0.05; 231 | # pi_obj[ss] = 1 -> phi_pi_obj; 232 | # pi[ss] = pi_obj[ss]-> phi_pi; 233 | phi_pi_obj = 1; 234 | # phi_pi = 1; 235 | rho_pi_dot = 0.924; 236 | }; 237 | }; 238 | 239 | 240 | 241 | block EQUILIBRIUM 242 | { 243 | identities 244 | { 245 | B[] = 0; 246 | }; 247 | }; 248 | -------------------------------------------------------------------------------- /tests/Test GCNs/full_nk_partial_ss.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | output logfile = TRUE; 4 | output LaTeX = TRUE; 5 | output LaTeX landscape = TRUE; 6 | }; 7 | 8 | assumptions 9 | { 10 | negative 11 | { 12 | TC[]; 13 | }; 14 | 15 | positive 16 | { 17 | shock_technology[], shock_preference[], pi[], pi_star[], pi_obj[], r[], r_G[], mc[], w[], w_star[], 18 | Y[], C[], I[], K[], L[], 19 | delta, beta, sigma_C, sigma_L, gamma_I, phi_H; 20 | }; 21 | }; 22 | 23 | block STEADY_STATE 24 | { 25 | identities 26 | { 27 | # Steady state values 28 | shock_technology[ss] = 1; 29 | shock_preference[ss] = 1; 30 | pi[ss] = 1; 31 | pi_star[ss] = 1; 32 | pi_obj[ss] = 1; 33 | B[ss] = 0; 34 | 35 | r[ss] = 1 / beta - (1 - delta); 36 | r_G[ss] = 1 / beta; 37 | 38 | mc[ss] = 1 / (1 + psi_p); 39 | }; 40 | 41 | }; 42 | 43 | 44 | block HOUSEHOLD 45 | { 46 | definitions 47 | { 48 | u[] = shock_preference[] * ( 49 | (C[] - phi_H * C[-1]) ^ (1 - sigma_C) / (1 - sigma_C) - 50 | L[] ^ (1 + sigma_L) / (1 + sigma_L)); 51 | }; 52 | controls 53 | { 54 | C[], I[], K[], B[]; 55 | }; 56 | 57 | objective 58 | { 59 | U[] = u[] + beta * E[][U[1]]; 60 | }; 61 | 62 | constraints 63 | { 64 | C[] + I[] + B[] / r_G[] = 65 | r[] * K[-1] + 66 | w[] * L[] + 67 | B[-1] / pi[] + 68 | Div[] : lambda[]; 69 | 70 | K[] = (1 - delta) * K[-1] + 71 | I[] * (1 - gamma_I / 2 * (I[] / I[-1] - 1) ^ 2) : q[]; 72 | }; 73 | 74 | calibration 75 | { 76 | delta = 0.025; 77 | beta = 0.99; 78 | 79 | sigma_C = 2; 80 | sigma_L = 1.5; 81 | 82 | gamma_I = 10; 83 | phi_H = 0.5; 84 | }; 85 | }; 86 | 87 | block WAGE_SETTING 88 | { 89 | definitions 90 | { 91 | L_d_star[] = (w[] / w_star[]) ^ ((1 + psi_w) / psi_w) * L[]; 92 | }; 93 | 94 | identities 95 | { 96 | LHS_w[] = RHS_w[]; 97 | 98 | LHS_w[] = 1 / (1 + psi_w) * w_star[] * lambda[] * L_d_star[] + 99 | beta * eta_w * E[][ 100 | pi[1] * (w_star[1] / w_star[]) ^ (1 / psi_w) * LHS_w[1] 101 | ]; 102 | 103 | RHS_w[] = shock_preference[] * L_d_star[] ^ (1 + sigma_L) + 104 | beta * eta_w * E[][ 105 | (pi[1] * w_star[1] / w_star[]) ^ ((1 + psi_w) * (1 + sigma_L) / psi_w) * 106 | RHS_w[1] 107 | ]; 108 | 109 | }; 110 | 111 | calibration 112 | { 113 | psi_w = 0.782; # Elasticity of substitution between forms of labor 114 | eta_w = 0.75; # Probability of not receiving the update signal 115 | }; 116 | }; 117 | 118 | block WAGE_EVOLUTION 119 | { 120 | identities 121 | { 122 | 1 = eta_w * (pi[] * w[] / w[-1]) ^ (1 / psi_w) + 123 | (1 - eta_w) * (w[] / w_star[]) ^ (1 / psi_w); 124 | }; 125 | }; 126 | 127 | 128 | block PREFERENCE_SHOCKS 129 | { 130 | identities 131 | { 132 | log(shock_preference[]) = rho_preference * log(shock_preference[-1]) + epsilon_preference[]; 133 | }; 134 | 135 | shocks 136 | { 137 | epsilon_preference[]; 138 | }; 139 | 140 | calibration 141 | { 142 | rho_preference = 0.95; 143 | }; 144 | }; 145 | 146 | 147 | block FIRM 148 | { 149 | controls 150 | { 151 | K[-1], L[]; 152 | }; 153 | 154 | objective 155 | { 156 | TC[] = -(L[] * w[] + K[-1] * r[]); 157 | }; 158 | 159 | constraints 160 | { 161 | Y[] = shock_technology[] * K[-1] ^ alpha * 162 | L[] ^ (1 - alpha) : mc[]; 163 | }; 164 | 165 | identities 166 | { 167 | Div[] = Y[] + TC[]; 168 | }; 169 | 170 | calibration 171 | { 172 | alpha = 0.35; 173 | }; 174 | }; 175 | 176 | 177 | block TECHNOLOGY_SHOCKS 178 | { 179 | identities 180 | { 181 | log(shock_technology[]) = rho_technology * log(shock_technology[-1]) + epsilon_Y[]; 182 | }; 183 | shocks 184 | { 185 | epsilon_Y[]; 186 | }; 187 | calibration 188 | { 189 | rho_technology = 0.95; 190 | }; 191 | }; 192 | 193 | 194 | block FIRM_PRICE_SETTING_PROBLEM 195 | { 196 | identities 197 | { 198 | LHS[] = (1 + psi_p) * RHS[]; 199 | 200 | LHS[] = lambda[] * Y[] * pi_star[] + 201 | beta * eta_p * E[][ 202 | pi_star[] / pi_star[1] * pi[1] ^ (1 / psi_p) * LHS[1]]; 203 | 204 | RHS[] = lambda[] * mc[] * Y[] + 205 | beta * eta_p * E[][ 206 | pi[1] ^ ((1 + psi_p) / psi_p) * RHS[1]]; 207 | }; 208 | 209 | calibration 210 | { 211 | psi_p = 0.6; 212 | eta_p = 0.75; 213 | }; 214 | }; 215 | 216 | 217 | block PRICE_EVOLUTION 218 | { 219 | identities 220 | { 221 | 1 = eta_p * pi[] ^ (1 / psi_p) + 222 | (1 - eta_p) * pi_star[] ^ (-1 / psi_p); 223 | }; 224 | }; 225 | 226 | 227 | block MONETARY_POLICY 228 | { 229 | identities 230 | { 231 | log(r_G[] / r_G[ss]) = gamma_R * log(r_G[-1] / r_G[ss]) + 232 | (1 - gamma_R) * log(pi_obj[]) + 233 | (1 - gamma_R) * gamma_pi * log(pi[] / pi[ss] - log(pi_obj[])) + 234 | (1 - gamma_R) * gamma_Y * log(Y[] / Y[-1]) + 235 | epsilon_R[]; 236 | 237 | log(pi_obj[]) = (1 - rho_pi_dot) * log(phi_pi_obj) + 238 | rho_pi_dot * log(pi_obj[-1]) + epsilon_pi[]; 239 | }; 240 | 241 | shocks 242 | { 243 | epsilon_R[], epsilon_pi[]; 244 | }; 245 | 246 | 247 | calibration 248 | { 249 | gamma_R = 0.9; 250 | gamma_pi = 1.5; 251 | gamma_Y = 0.05; 252 | # pi_obj[ss] = 1 -> phi_pi_obj; 253 | # pi[ss] = pi_obj[ss]-> phi_pi; 254 | phi_pi_obj = 1; 255 | # phi_pi = 1; 256 | rho_pi_dot = 0.924; 257 | }; 258 | }; 259 | 260 | 261 | 262 | block EQUILIBRIUM 263 | { 264 | identities 265 | { 266 | B[] = 0; 267 | }; 268 | }; 269 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_1.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | 4 | }; 5 | 6 | block HOUSEHOLD 7 | { 8 | definitions 9 | { 10 | u[] = (C[] ^ (1 - gamma) - 1) / (1 - gamma); 11 | }; 12 | 13 | controls 14 | { 15 | C[], K[]; 16 | }; 17 | 18 | objective 19 | { 20 | U[] = u[] + beta * E[][U[1]]; 21 | }; 22 | 23 | constraints 24 | { 25 | C[] + K[] - (1 - delta) * K[-1] = A[] * K[-1] ^ alpha : lambda[]; 26 | }; 27 | 28 | identities 29 | { 30 | log(A[]) = rho * log(A[-1]) + epsilon[]; 31 | }; 32 | 33 | shocks 34 | { 35 | epsilon[]; 36 | }; 37 | 38 | calibration 39 | { 40 | alpha = 0.4; 41 | beta = 0.99; 42 | delta = 0.02; 43 | rho = 0.95; 44 | gamma = 1.5; 45 | }; 46 | 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_1_dist.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | 4 | }; 5 | 6 | tryreduce 7 | { 8 | 9 | }; 10 | 11 | block HOUSEHOLD 12 | { 13 | definitions 14 | { 15 | u[] = (C[] ^ (1 - gamma) - 1) / (1 - gamma); 16 | }; 17 | 18 | controls 19 | { 20 | C[], K[]; 21 | }; 22 | 23 | objective 24 | { 25 | U[] = u[] + beta * E[][U[1]]; 26 | }; 27 | 28 | constraints 29 | { 30 | C[] + K[] - (1 - delta) * K[-1] = A[] * K[-1] ^ alpha : lambda[]; 31 | }; 32 | 33 | identities 34 | { 35 | log(A[]) = rho * log(A[-1]) + epsilon[]; 36 | }; 37 | 38 | shocks 39 | { 40 | epsilon[] ~ Normal(mu=0, sigma=sigma_epsilon); 41 | }; 42 | 43 | calibration 44 | { 45 | alpha ~ Beta(mu=0.5, sigma=0.1) = 0.4; 46 | beta = 0.99; 47 | delta = 0.02; 48 | rho ~ Beta(mu=0.95, sigma=0.04) = 0.95; 49 | gamma ~ HalfNormal(sigma=1) = 1.5; 50 | 51 | sigma_epsilon ~ InverseGamma(mu=0.1, sigma=0.01) = 0.01; 52 | }; 53 | 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_1_duplicate_params.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | 4 | }; 5 | 6 | block STEADY_STATE 7 | { 8 | identities 9 | { 10 | A[ss] = 1; 11 | }; 12 | }; 13 | 14 | block HOUSEHOLD 15 | { 16 | definitions 17 | { 18 | u[] = (C[] ^ (1 - gamma) - 1) / (1 - gamma); 19 | }; 20 | 21 | controls 22 | { 23 | C[], K[]; 24 | }; 25 | 26 | objective 27 | { 28 | U[] = u[] + beta * E[][U[1]]; 29 | }; 30 | 31 | constraints 32 | { 33 | C[] + K[] - (1 - delta) * K[-1] = A[] * K[-1] ^ alpha : lambda[]; 34 | }; 35 | 36 | identities 37 | { 38 | log(A[]) = rho * log(A[-1]) + epsilon[]; 39 | }; 40 | 41 | shocks 42 | { 43 | epsilon[]; 44 | }; 45 | 46 | calibration 47 | { 48 | alpha = 0.4; 49 | beta = 0.99; 50 | delta = 0.02; 51 | rho = 0.95; 52 | gamma = 1.5; 53 | gamma = 2.0; 54 | }; 55 | 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_1_duplicate_params_2.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | 4 | }; 5 | 6 | block STEADY_STATE 7 | { 8 | identities 9 | { 10 | A[ss] = 1; 11 | }; 12 | }; 13 | 14 | block HOUSEHOLD 15 | { 16 | definitions 17 | { 18 | u[] = (C[] ^ (1 - gamma) - 1) / (1 - gamma); 19 | }; 20 | 21 | controls 22 | { 23 | C[], K[]; 24 | }; 25 | 26 | objective 27 | { 28 | U[] = u[] + beta * E[][U[1]]; 29 | }; 30 | 31 | constraints 32 | { 33 | C[] + K[] - (1 - delta) * K[-1] = A[] * K[-1] ^ alpha : lambda[]; 34 | }; 35 | 36 | identities 37 | { 38 | log(A[]) = rho * log(A[-1]) + epsilon[]; 39 | }; 40 | 41 | shocks 42 | { 43 | epsilon[]; 44 | }; 45 | 46 | calibration 47 | { 48 | alpha = 0.4; 49 | beta = 0.99; 50 | delta = 0.02; 51 | rho = 0.95; 52 | gamma = 1.5; 53 | }; 54 | }; 55 | 56 | block DUPLICATE_PARAMETER 57 | { 58 | calibration 59 | { 60 | gamma = 3; 61 | beta = 2; 62 | }; 63 | }; 64 | 65 | block MORE_DUPLICATE_PARAMETERS 66 | { 67 | calibration 68 | { 69 | alpha = 0.333; 70 | }; 71 | }; 72 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_1_ss.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | output logfile = FALSE; 4 | output LaTeX = FALSE; 5 | }; 6 | 7 | tryreduce 8 | { 9 | C[]; 10 | }; 11 | 12 | block STEADY_STATE 13 | { 14 | definitions 15 | { 16 | L_num = theta * (1 - alpha) * (1 - beta * (1 - delta)); 17 | L_denom = 1 - alpha * theta - beta * (1 - delta * (1 - alpha) - alpha * theta); 18 | }; 19 | 20 | identities 21 | { 22 | L[ss] = L_num / L_denom; 23 | K[ss] = (((1 - alpha * theta) * L[ss] - theta * (1 - alpha)) / (delta * (1 - theta) * L[ss])) ^ 24 | (1 / (1 - alpha)) * L[ss]; 25 | A[ss] = 1; 26 | 27 | Y[ss] = K[ss] ^ alpha * L[ss] ^ (1 - alpha); 28 | I[ss] = delta * K[ss]; 29 | C[ss] = Y[ss] - I[ss]; 30 | 31 | lambda[ss] = theta * (C[ss] ^ theta * (1 - L[ss]) ^ (1 - theta)) ^ (1 - tau) / C[ss]; 32 | q[ss] = lambda[ss]; 33 | U[ss] = (C[ss] ^ theta * (1 - L[ss]) ^ (1 - theta)) ^ (1 - tau) / ((1 - beta) * (1 - tau)); 34 | }; 35 | }; 36 | 37 | block HOUSEHOLD 38 | { 39 | definitions 40 | { 41 | u[] = (C[] ^ theta * (1 - L[]) ^ (1 - theta)) ^ (1 - tau) / (1 - tau); 42 | }; 43 | 44 | controls 45 | { 46 | C[], L[], I[], K[], Y[]; 47 | }; 48 | 49 | objective 50 | { 51 | U[] = u[] + beta * E[][U[1]]; 52 | }; 53 | 54 | constraints 55 | { 56 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha); 57 | C[] + I[] = Y[] : lambda[]; 58 | K[] = I[] + (1 - delta) * K[-1] : q[]; 59 | }; 60 | 61 | identities 62 | { 63 | log(A[]) = rho * log(A[-1]) + epsilon[]; 64 | }; 65 | 66 | shocks 67 | { 68 | epsilon[]; 69 | }; 70 | 71 | calibration 72 | { 73 | # L[ss] / K[ss] = 0.36 -> alpha; 74 | alpha ~ Beta(alpha=1, beta=1) = 0.35; 75 | theta ~ Beta(alpha=1, beta=1) = 0.357; 76 | beta ~ Beta(alpha=1, beta=1) = 0.99; 77 | delta ~ Beta(alpha=1, beta=1) = 0.02; 78 | tau ~ Gamma(alpha=2, beta=1) = 2; 79 | rho ~ Beta(alpha=1, beta=1) = 0.95; 80 | }; 81 | 82 | 83 | }; 84 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_1_ss_2shock.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | definitions 4 | { 5 | L_num = theta * (1 - alpha) * (1 - beta * (1 - delta)); 6 | L_denom = 1 - alpha * theta - beta * (1 - delta * (1 - alpha) - alpha * theta); 7 | }; 8 | 9 | identities 10 | { 11 | L[ss] = L_num / L_denom; 12 | K[ss] = (((1 - alpha * theta) * L[ss] - theta * (1 - alpha)) / (delta * (1 - theta) * L[ss])) ^ 13 | (1 / (1 - alpha)) * L[ss]; 14 | A[ss] = 1; 15 | B[ss] = 1; 16 | 17 | Y[ss] = K[ss] ^ alpha * L[ss] ^ (1 - alpha); 18 | I[ss] = delta * K[ss]; 19 | C[ss] = Y[ss] - I[ss]; 20 | 21 | lambda[ss] = theta * (C[ss] ^ theta * (1 - L[ss]) ^ (1 - theta)) ^ (1 - tau) / C[ss]; 22 | q[ss] = lambda[ss]; 23 | U[ss] = (C[ss] ^ theta * (1 - L[ss]) ^ (1 - theta)) ^ (1 - tau) / ((1 - beta) * (1 - tau)); 24 | }; 25 | }; 26 | 27 | block HOUSEHOLD 28 | { 29 | definitions 30 | { 31 | u[] = B[] * (C[] ^ theta * (1 - L[]) ^ (1 - theta)) ^ (1 - tau) / (1 - tau); 32 | }; 33 | 34 | controls 35 | { 36 | C[], L[], I[], K[], Y[]; 37 | }; 38 | 39 | objective 40 | { 41 | U[] = u[] + beta * E[][U[1]]; 42 | }; 43 | 44 | constraints 45 | { 46 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha); 47 | C[] + I[] = Y[] : lambda[]; 48 | K[] = I[] + (1 - delta) * K[-1] : q[]; 49 | }; 50 | 51 | identities 52 | { 53 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 54 | log(B[]) = rho_B * log(B[-1]) + epsilon_B[]; 55 | }; 56 | 57 | shocks 58 | { 59 | epsilon_A[], epsilon_B[]; 60 | }; 61 | 62 | calibration 63 | { 64 | alpha = 0.35; 65 | theta = 0.357; 66 | beta = 0.99; 67 | delta = 0.02; 68 | tau = 2; 69 | rho_A = 0.95; 70 | rho_B = 0.95; 71 | }; 72 | }; 73 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_1_ss_error.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | 4 | }; 5 | 6 | block STEADY_STATE 7 | { 8 | identities 9 | { 10 | A[ss] = 10; 11 | }; 12 | }; 13 | 14 | block HOUSEHOLD 15 | { 16 | definitions 17 | { 18 | u[] = (C[] ^ (1 - gamma) - 1) / (1 - gamma); 19 | }; 20 | 21 | controls 22 | { 23 | C[], K[]; 24 | }; 25 | 26 | objective 27 | { 28 | U[] = u[] + beta * E[][U[1]]; 29 | }; 30 | 31 | constraints 32 | { 33 | C[] + K[] - (1 - delta) * K[-1] = A[] * K[-1] ^ alpha : lambda[]; 34 | }; 35 | 36 | identities 37 | { 38 | log(A[]) = rho * log(A[-1]) + epsilon[]; 39 | }; 40 | 41 | shocks 42 | { 43 | epsilon[]; 44 | }; 45 | 46 | calibration 47 | { 48 | alpha = 0.4; 49 | beta = 0.99; 50 | delta = 0.02; 51 | rho = 0.95; 52 | gamma = 1.5; 53 | }; 54 | }; 55 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_2.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | output logfile = FALSE; 4 | output LaTeX = FALSE; 5 | }; 6 | 7 | tryreduce 8 | { 9 | C[]; 10 | }; 11 | 12 | assumptions 13 | { 14 | positive 15 | { 16 | Y[], C[], I[], K[], L[], A[], theta, beta, delta, tau, rho, alpha; 17 | }; 18 | }; 19 | 20 | block HOUSEHOLD 21 | { 22 | definitions 23 | { 24 | u[] = (C[] ^ theta * (1 - L[]) ^ (1 - theta)) ^ (1 - tau) / (1 - tau); 25 | }; 26 | 27 | controls 28 | { 29 | C[], L[], I[], K[], Y[]; 30 | }; 31 | 32 | objective 33 | { 34 | U[] = u[] + beta * E[][U[1]]; 35 | }; 36 | 37 | constraints 38 | { 39 | Y[] = A[] * K[] ^ alpha * L[] ^ (1 - alpha) + Theta + zeta; 40 | I[] = Y[] - C[] : lambda[]; 41 | K[] = I[] + (1 - delta) * K[-1] : q[]; 42 | }; 43 | 44 | identities 45 | { 46 | log(A[]) = rho * log(A[-1]) + epsilon[]; 47 | }; 48 | 49 | shocks 50 | { 51 | epsilon[]; 52 | }; 53 | 54 | calibration 55 | { 56 | L[ss] / K[ss] = 0.36 -> alpha; 57 | theta = 0.357; 58 | beta = 1 / 1.01; 59 | delta = 0.02; 60 | tau = 2; 61 | 62 | rho = 0.95; 63 | 64 | Theta = rho * beta + 3; 65 | zeta = -log(theta); 66 | }; 67 | 68 | 69 | }; 70 | -------------------------------------------------------------------------------- /tests/Test GCNs/one_block_2_no_extra.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | output logfile = FALSE; 4 | output LaTeX = FALSE; 5 | }; 6 | 7 | tryreduce 8 | { 9 | C[]; 10 | }; 11 | 12 | assumptions 13 | { 14 | positive 15 | { 16 | Y[], C[], I[], K[], L[], A[], theta, beta, delta, tau, rho, alpha; 17 | }; 18 | }; 19 | 20 | block HOUSEHOLD 21 | { 22 | definitions 23 | { 24 | u[] = (C[] ^ theta * (1 - L[]) ^ (1 - theta)) ^ (1 - tau) / (1 - tau); 25 | }; 26 | 27 | controls 28 | { 29 | C[], L[], I[], K[], Y[]; 30 | }; 31 | 32 | objective 33 | { 34 | U[] = u[] + beta * E[][U[1]]; 35 | }; 36 | 37 | constraints 38 | { 39 | Y[] = A[] * K[] ^ alpha * L[] ^ (1 - alpha); 40 | I[] = Y[] - C[] : lambda[]; 41 | K[] = I[] + (1 - delta) * K[-1] : q[]; 42 | }; 43 | 44 | identities 45 | { 46 | log(A[]) = rho * log(A[-1]) + epsilon[]; 47 | }; 48 | 49 | shocks 50 | { 51 | epsilon[]; 52 | }; 53 | 54 | calibration 55 | { 56 | L[ss] / K[ss] = 0.36 -> alpha; 57 | theta = 0.357; 58 | beta = 1 / 1.01; 59 | delta = 0.02; 60 | tau = 2; 61 | 62 | rho = 0.95; 63 | }; 64 | }; 65 | -------------------------------------------------------------------------------- /tests/Test GCNs/open_rbc.gcn: -------------------------------------------------------------------------------- 1 | assumptions 2 | { 3 | positive 4 | { 5 | A[], r[], N[], K[], Y[], I[], C[]; 6 | }; 7 | }; 8 | 9 | block STEADY_STATE 10 | { 11 | identities 12 | { 13 | A[ss] = 1; 14 | IIP[ss] = IIPbar; 15 | r[ss] = rstar; 16 | r_given[ss] = r[ss]; 17 | KtoN[ss] = (alpha/(r[ss]+delta))^(1/(1-alpha)); 18 | N[ss] = ((1-alpha)*(KtoN[ss])^alpha)^(1/(omega-1)); 19 | K[ss] = KtoN[ss]*N[ss]; 20 | Y[ss] = A[ss] * K[ss] ^ alpha * N[ss] ^ (1 - alpha); 21 | I[ss] = delta * K[ss]; 22 | C[ss] = r[ss]*IIP[ss]+Y[ss]-I[ss]; 23 | u[ss] = 1/(1-gamma)*((C[ss]-1/omega*N[ss]^omega)^(1-gamma)-1); 24 | U[ss] = 1 / (1 - beta) * u[ss]; 25 | Cadjcost[ss] = 0; 26 | TB[ss] = Y[ss] - C[ss] - I[ss] - Cadjcost[ss]; 27 | TBtoY[ss] = TB[ss] / Y[ss]; 28 | CA[ss] = TB[ss] + r[ss]*IIP[ss]; 29 | lambda[ss] = (C[ss] - N[ss] ^ omega / omega) ^ (-gamma); 30 | }; 31 | }; 32 | 33 | 34 | block HOUSEHOLD 35 | { 36 | definitions 37 | { 38 | u[] = 1/(1-gamma)*((C[] - 1 / omega * N[] ^ omega) ^ (1 - gamma) - 1); 39 | I[] = K[] - (1 - delta) * K[-1]; 40 | Cadjcost[] = psi/2*(K[] - K[-1])^2; 41 | Y[] = A[] * K[-1] ^ alpha * N[] ^ (1 - alpha); 42 | }; 43 | 44 | controls 45 | { 46 | C[], N[], K[], IIP[]; 47 | }; 48 | 49 | objective 50 | { 51 | U[] = u[] + beta * E[][U[1]]; 52 | }; 53 | 54 | constraints 55 | { 56 | C[] + I[] + Cadjcost[] + IIP[] = Y[] + (1+r_given[-1])*IIP[-1] : lambda[]; 57 | }; 58 | 59 | identities 60 | { 61 | TB[] = Y[] - C[] - I[] - Cadjcost[]; 62 | KtoN[] = K[] / N[]; 63 | TBtoY[] = TB[] / Y[]; 64 | CA[] = TB[] + r[-1]*IIP[-1]; 65 | r[] = rstar + psi2*(exp(IIPbar-IIP[])-1); 66 | r_given[] = r[]; 67 | }; 68 | 69 | calibration 70 | { 71 | beta = 0.990099; 72 | delta = 0.025; 73 | gamma_rv ~ HalfNormal(sigma=5) = 1; 74 | omega_rv ~ HalfNormal(sigma=5) = 0.455; 75 | gamma = 1 + gamma_rv; 76 | omega = 1 + omega_rv; 77 | psi2 = 0.000742; 78 | psi = 0.028; 79 | alpha ~ Beta(alpha=5, beta=5) = 0.32; 80 | rstar = 1 / beta - 1; 81 | IIPbar = 0; 82 | }; 83 | }; 84 | 85 | 86 | block TECHNOLOGY_SHOCKS 87 | { 88 | identities 89 | { 90 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 91 | }; 92 | 93 | calibration 94 | { 95 | rho_A ~ Beta(alpha=3, beta=1) = 0.42; 96 | }; 97 | 98 | shocks 99 | { 100 | epsilon_A[]; 101 | }; 102 | }; 103 | 104 | block EQULIBRIUM 105 | { 106 | identities 107 | { 108 | I[] = K[] - (1 - delta) * K[-1]; 109 | Y[] = A[] * K[-1] ^ alpha * N[] ^ (1 - alpha); 110 | }; 111 | }; 112 | -------------------------------------------------------------------------------- /tests/Test GCNs/open_rbc_extra_params.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | identities 4 | { 5 | A[ss] = 1; 6 | IIP[ss] = IIPbar; 7 | r[ss] = rstar; 8 | r_given[ss] = r[ss]; 9 | KtoN[ss] = (alpha/(r[ss]+delta))^(1/(1-alpha)); 10 | N[ss] = ((1-alpha)*(KtoN[ss])^alpha)^(1/(omega-1)); 11 | K[ss] = KtoN[ss]*N[ss]; 12 | Y[ss] = A[ss] * K[ss] ^ alpha * N[ss] ^ (1 - alpha); 13 | I[ss] = delta * K[ss]; 14 | C[ss] = r[ss]*IIP[ss]+Y[ss]-I[ss]; 15 | u[ss] = 1/(1-gamma)*((C[ss]-1/omega*N[ss]^omega)^(1-gamma)-1); 16 | U[ss] = 1 / (1 - beta) * u[ss]; 17 | Cadjcost[ss] = 0; 18 | TB[ss] = Y[ss] - C[ss] - I[ss] - Cadjcost[ss]; 19 | TBtoY[ss] = TB[ss] / Y[ss]; 20 | CA[ss] = TB[ss] + r[ss]*IIP[ss]; 21 | lambda[ss] = (C[ss] - N[ss] ^ omega / omega) ^ (-gamma); 22 | }; 23 | }; 24 | 25 | 26 | block HOUSEHOLD 27 | { 28 | definitions 29 | { 30 | u[] = 1/(1-gamma)*((C[] - 1 / omega * N[] ^ omega) ^ (1 - gamma) - 1); 31 | I[] = K[] - (1 - delta) * K[-1]; 32 | Cadjcost[] = psi/2*(K[] - K[-1])^2; 33 | Y[] = A[] * K[-1] ^ alpha * N[] ^ (1 - alpha); 34 | }; 35 | 36 | controls 37 | { 38 | C[], N[], K[], IIP[]; 39 | }; 40 | 41 | objective 42 | { 43 | U[] = u[] + beta * E[][U[1]]; 44 | }; 45 | 46 | constraints 47 | { 48 | C[] + I[] + Cadjcost[] + IIP[] = Y[] + (1+r_given[-1])*IIP[-1] : lambda[]; 49 | }; 50 | 51 | identities 52 | { 53 | TB[] = Y[] - C[] - I[] - Cadjcost[]; 54 | KtoN[] = K[] / N[]; 55 | TBtoY[] = TB[] / Y[]; 56 | CA[] = TB[] + r[-1]*IIP[-1]; 57 | r[] = rstar + psi2*(exp(IIPbar-IIP[])-1); 58 | r_given[] = r[]; 59 | }; 60 | 61 | calibration 62 | { 63 | beta = 0.990099; 64 | delta = 0.025; 65 | gamma = 2; 66 | omega = 1.455; 67 | psi2 = 0.000742; 68 | psi = 0.028; 69 | alpha = 0.32; 70 | rstar = 1 - 1 / beta; 71 | IIPbar = 0; 72 | extra_param = 123; 73 | }; 74 | }; 75 | 76 | 77 | block TECHNOLOGY_SHOCKS 78 | { 79 | identities 80 | { 81 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 82 | }; 83 | 84 | calibration 85 | { 86 | rho_A = 0.42; 87 | sigma_epsilon_A = 0.01; 88 | }; 89 | 90 | shocks 91 | { 92 | epsilon_A[]; 93 | }; 94 | }; 95 | 96 | block EQULIBRIUM 97 | { 98 | identities 99 | { 100 | I[] = K[] - (1 - delta) * K[-1]; 101 | Y[] = A[] * K[-1] ^ alpha * N[] ^ (1 - alpha); 102 | }; 103 | }; 104 | -------------------------------------------------------------------------------- /tests/Test GCNs/open_rbc_orphan_params.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | identities 4 | { 5 | A[ss] = 1; 6 | IIP[ss] = IIPbar; 7 | r[ss] = rstar; 8 | r_given[ss] = r[ss]; 9 | KtoN[ss] = (alpha/(r[ss]+delta))^(1/(1-alpha)); 10 | N[ss] = ((1-alpha)*(KtoN[ss])^alpha)^(1/(omega-1)); 11 | K[ss] = KtoN[ss]*N[ss]; 12 | Y[ss] = A[ss] * K[ss] ^ alpha * N[ss] ^ (1 - alpha); 13 | I[ss] = delta * K[ss]; 14 | C[ss] = r[ss]*IIP[ss]+Y[ss]-I[ss]; 15 | u[ss] = 1/(1-gamma)*((C[ss]-1/omega*N[ss]^omega)^(1-gamma)-1); 16 | U[ss] = 1 / (1 - beta) * u[ss]; 17 | Cadjcost[ss] = 0; 18 | TB[ss] = Y[ss] - C[ss] - I[ss] - Cadjcost[ss]; 19 | TBtoY[ss] = TB[ss] / Y[ss]; 20 | CA[ss] = TB[ss] + r[ss]*IIP[ss]; 21 | lambda[ss] = (C[ss] - N[ss] ^ omega / omega) ^ (-gamma); 22 | }; 23 | }; 24 | 25 | 26 | block HOUSEHOLD 27 | { 28 | definitions 29 | { 30 | u[] = 1/(1-gamma)*((C[] - 1 / omega * N[] ^ omega) ^ (1 - gamma) - 1); 31 | I[] = K[] - (1 - delta) * K[-1]; 32 | Cadjcost[] = psi/2*(K[] - K[-1])^2; 33 | Y[] = A[] * K[-1] ^ alpha * N[] ^ (1 - alpha); 34 | }; 35 | 36 | controls 37 | { 38 | C[], N[], K[], IIP[]; 39 | }; 40 | 41 | objective 42 | { 43 | U[] = u[] + beta * E[][U[1]]; 44 | }; 45 | 46 | constraints 47 | { 48 | C[] + I[] + Cadjcost[] + IIP[] = Y[] + (1+r_given[-1])*IIP[-1] : lambda[]; 49 | }; 50 | 51 | identities 52 | { 53 | TB[] = Y[] - C[] - I[] - Cadjcost[]; 54 | KtoN[] = K[] / N[]; 55 | TBtoY[] = TB[] / Y[] + orphan; 56 | CA[] = TB[] + r[-1]*IIP[-1]; 57 | r[] = rstar + psi2*(exp(IIPbar-IIP[])-1); 58 | r_given[] = r[]; 59 | }; 60 | 61 | calibration 62 | { 63 | beta = 0.990099; 64 | delta = 0.025; 65 | gamma = 2; 66 | omega = 1.455; 67 | psi2 = 0.000742; 68 | psi = 0.028; 69 | alpha = 0.32; 70 | rstar = 1 - 1 / beta; 71 | IIPbar = 0; 72 | }; 73 | }; 74 | 75 | 76 | block TECHNOLOGY_SHOCKS 77 | { 78 | identities 79 | { 80 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 81 | }; 82 | 83 | calibration 84 | { 85 | rho_A = 0.42; 86 | sigma_epsilon_A = 0.01; 87 | }; 88 | 89 | shocks 90 | { 91 | epsilon_A[]; 92 | }; 93 | }; 94 | 95 | block EQULIBRIUM 96 | { 97 | identities 98 | { 99 | I[] = K[] - (1 - delta) * K[-1]; 100 | Y[] = A[] * K[-1] ^ alpha * N[] ^ (1 - alpha); 101 | }; 102 | }; 103 | -------------------------------------------------------------------------------- /tests/Test GCNs/pert_fails.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | identities 4 | { 5 | A[ss] = 1; 6 | R[ss] = (1 / beta - (1 - delta)); 7 | W[ss] = (1 - alpha) ^ (1 / (1 - alpha)) * (alpha / R[ss]) ^ (alpha / (1 - alpha)); 8 | Y[ss] = (R[ss] / (R[ss] - delta * alpha)) ^ (sigma / (sigma + phi)) * 9 | ((1 - alpha) ^ (-phi) * (W[ss]) ^ (1 + phi)) ^ (1 / (sigma + phi)); 10 | K[ss] = alpha * Y[ss] / R[ss]; 11 | I[ss] = delta * K[ss]; 12 | C[ss] = Y[ss] - I[ss]; 13 | L[ss] = (1 - alpha) * Y[ss] / W[ss]; 14 | }; 15 | }; 16 | 17 | block SYSTEM_EQUATIONS 18 | { 19 | identities 20 | { 21 | #1. Labor supply 22 | W[] = sigma * C[] + phi * L[]; 23 | 24 | #2. Euler Equation 25 | sigma / beta * (E[][C[1]] - C[]) = R[ss] * E[][R[1]]; 26 | 27 | #3. Law of motion of capital -- Timings have been changed to cause Gensys to fail 28 | K[] = (1 - delta) * K[] + delta * I[]; 29 | 30 | #4. Production Function -- Timings have been changed to cause Gensys to fail 31 | Y[] = A[] + alpha * E[][K[1]] + (1 - alpha) * L[]; 32 | 33 | #5. Demand for capital 34 | R[] = Y[] - K[-1]; 35 | 36 | #6. Demand for labor 37 | W[] = Y[] - L[]; 38 | 39 | #7. Equlibrium Condition 40 | Y[ss] * Y[] = C[ss] * C[] + I[ss] * I[]; 41 | 42 | #8. Productivity Shock 43 | A[] = rho_A * A[-1] + epsilon_A[]; 44 | 45 | }; 46 | 47 | shocks 48 | { 49 | epsilon_A[]; 50 | }; 51 | 52 | calibration 53 | { 54 | sigma = 2; 55 | phi = 1.5; 56 | alpha = 0.35; 57 | beta = 0.985; 58 | delta = 0.025; 59 | rho_A = 0.95; 60 | }; 61 | 62 | }; 63 | -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_2_block.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | output logfile = TRUE; 4 | output LaTeX = TRUE; 5 | output LaTeX landscape = TRUE; 6 | }; 7 | 8 | 9 | block HOUSEHOLD 10 | { 11 | definitions 12 | { 13 | u[] = C[] ^ (1 - sigma_C) / (1 - sigma_C) - 14 | L[] ^ (1 + sigma_L) / (1 + sigma_L); 15 | }; 16 | controls 17 | { 18 | K[], C[], L[], I[]; 19 | }; 20 | objective 21 | { 22 | U[] = u[] + beta * E[][U[1]]; 23 | }; 24 | constraints 25 | { 26 | C[] + I[] = w[] * L[] + r[] * K[-1] : lambda[]; 27 | K[] = (1 - delta) * K[-1] + I[] : q[]; 28 | }; 29 | 30 | calibration 31 | { 32 | beta = 0.985; 33 | delta = 0.025; 34 | sigma_C = 2; 35 | sigma_L = 1.5; 36 | }; 37 | }; 38 | 39 | 40 | block FIRM 41 | { 42 | controls 43 | { 44 | K[-1], L[]; 45 | }; 46 | 47 | objective 48 | { 49 | TC[] = -(w[] * L[] + r[] * K[-1]); 50 | }; 51 | 52 | constraints 53 | { 54 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : P[]; 55 | }; 56 | 57 | identities 58 | { 59 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 60 | P[] = 1; 61 | }; 62 | 63 | shocks 64 | { 65 | epsilon_A[]; 66 | }; 67 | 68 | calibration 69 | { 70 | alpha = 0.35; 71 | rho_A = 0.95; 72 | }; 73 | }; 74 | -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_2_block_partial_ss.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | identities 4 | { 5 | A[ss] = 1; 6 | r[ss] = 1 / beta - (1 - delta); 7 | }; 8 | }; 9 | 10 | block HOUSEHOLD 11 | { 12 | definitions 13 | { 14 | u[] = C[] ^ (1 - sigma_C) / (1 - sigma_C) - 15 | L[] ^ (1 + sigma_L) / (1 + sigma_L); 16 | }; 17 | controls 18 | { 19 | K[], C[], L[], I[]; 20 | }; 21 | objective 22 | { 23 | U[] = u[] + beta * E[][U[1]]; 24 | }; 25 | constraints 26 | { 27 | C[] + I[] = w[] * L[] + r[] * K[-1] : lambda[]; 28 | K[] = (1 - delta) * K[-1] + I[] : q[]; 29 | }; 30 | 31 | calibration 32 | { 33 | beta = 0.985; 34 | delta = 0.025; 35 | sigma_C = 2; 36 | sigma_L = 1.5; 37 | }; 38 | }; 39 | 40 | 41 | block FIRM 42 | { 43 | controls 44 | { 45 | K[-1], L[]; 46 | }; 47 | 48 | objective 49 | { 50 | TC[] = -(w[] * L[] + r[] * K[-1]); 51 | }; 52 | 53 | constraints 54 | { 55 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : P[]; 56 | }; 57 | 58 | identities 59 | { 60 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 61 | P[] = 1; 62 | }; 63 | 64 | shocks 65 | { 66 | epsilon_A[]; 67 | }; 68 | 69 | calibration 70 | { 71 | alpha = 0.35; 72 | rho_A = 0.95; 73 | }; 74 | }; 75 | -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_2_block_ss.gcn: -------------------------------------------------------------------------------- 1 | block STEADY_STATE 2 | { 3 | identities 4 | { 5 | A[ss] = 1; 6 | r[ss] = 1 / beta - (1 - delta); 7 | w[ss] = (1 - alpha) * (alpha / r[ss]) ^ (alpha / (1 - alpha)); 8 | Y[ss] = (r[ss] / (r[ss] - delta * alpha)) ^ (sigma_C / (sigma_C + sigma_L)) * 9 | (w[ss] * (w[ss] / (1 - alpha)) ^ sigma_L) ^ (1 / (sigma_C + sigma_L)); 10 | I[ss] = delta * alpha / r[ss] * Y[ss]; 11 | C[ss] = ((1 - alpha) ^ (-sigma_L) * w[ss] ^ (1 + sigma_L)) ^ (1 / sigma_C) * Y[ss] ^ (-sigma_L / sigma_C); 12 | K[ss] = alpha * Y[ss] / r[ss]; 13 | L[ss] = (1 - alpha) * Y[ss] / w[ss]; 14 | U[ss] = 1 / (1 - beta) * (C[ss] ^ (1 - sigma_C) / (1 - sigma_C) - L[ss] ^ (1 + sigma_L) / (1 + sigma_L)); 15 | lambda[ss] = C[ss] ^ (-sigma_C); 16 | q[ss] = lambda[ss]; 17 | TC[ss] = -(w[ss] * L[ss] + r[ss] * K[ss]); 18 | }; 19 | }; 20 | 21 | block HOUSEHOLD 22 | { 23 | definitions 24 | { 25 | u[] = C[] ^ (1 - sigma_C) / (1 - sigma_C) - 26 | L[] ^ (1 + sigma_L) / (1 + sigma_L); 27 | }; 28 | controls 29 | { 30 | K[], C[], L[], I[]; 31 | }; 32 | objective 33 | { 34 | U[] = u[] + beta * E[][U[1]]; 35 | }; 36 | constraints 37 | { 38 | C[] + I[] = w[] * L[] + r[] * K[-1] : lambda[]; 39 | K[] = (1 - delta) * K[-1] + I[] : q[]; 40 | }; 41 | 42 | calibration 43 | { 44 | beta = 0.985; 45 | delta = 0.025; 46 | sigma_C = 2; 47 | sigma_L = 1.5; 48 | }; 49 | }; 50 | 51 | 52 | block FIRM 53 | { 54 | controls 55 | { 56 | K[-1], L[]; 57 | }; 58 | 59 | objective 60 | { 61 | TC[] = -(w[] * L[] + r[] * K[-1]); 62 | }; 63 | 64 | constraints 65 | { 66 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : P[]; 67 | }; 68 | 69 | identities 70 | { 71 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 72 | P[] = 1; 73 | }; 74 | 75 | shocks 76 | { 77 | epsilon_A[]; 78 | }; 79 | 80 | calibration 81 | { 82 | alpha = 0.35; 83 | rho_A = 0.95; 84 | }; 85 | }; 86 | -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_firm_capital.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | Pi[], U[]; 4 | }; 5 | 6 | block STEADYSTATE 7 | { 8 | 9 | definitions 10 | { 11 | # Capital/Labor Ratio 12 | N[ss] = (alpha * beta * A[ss] / (1 - beta * (1 - delta))) 13 | ^ (1 / (1 - alpha)); 14 | }; 15 | 16 | identities 17 | { 18 | A[ss] = 1.0; 19 | Pi[ss] = 0.0; 20 | L[ss] = (1 - alpha) / Theta / (1 - delta * N[ss] ^ (1 - alpha)); 21 | K[ss] = N[ss] * L[ss]; 22 | 23 | w[ss] = (1 - alpha) * N[ss] ^ alpha; 24 | 25 | Y[ss] = A[ss] * K[ss] ^ alpha * L[ss] ^ (1 - alpha); 26 | I[ss] = delta * K[ss]; 27 | C[ss] = Y[ss] - I[ss]; 28 | 29 | U[ss] = (1 / (1 - beta)) * (log(C[ss]) - Theta * L[ss]); 30 | lambda[ss] = 1 / C[ss]; 31 | }; 32 | }; 33 | 34 | block HOUSEHOLD 35 | { 36 | definitions 37 | { 38 | u[] = log(C[]) - Theta * L[]; 39 | }; 40 | 41 | objective 42 | { 43 | U[] = u[] + beta * E[][U[1]]; 44 | }; 45 | 46 | controls 47 | { 48 | C[], L[]; 49 | }; 50 | 51 | constraints 52 | { 53 | @exclude 54 | C[] = w[] * L[] + Pi[] : lambda[]; 55 | }; 56 | 57 | calibration 58 | { 59 | beta = 0.99; 60 | Theta = 1; 61 | }; 62 | }; 63 | 64 | block FIRM 65 | { 66 | definitions 67 | { 68 | pi[] = Y[] - (w[] * L[] + I[]); 69 | }; 70 | 71 | objective 72 | { 73 | Pi[] = pi[] + beta * E[][lambda[1] / lambda[] * Pi[1]]; 74 | }; 75 | 76 | controls 77 | { 78 | Y[], L[], K[], I[]; 79 | }; 80 | 81 | constraints 82 | { 83 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha); 84 | K[] = (1 - delta) * K[-1] + I[]; 85 | }; 86 | 87 | identities 88 | { 89 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 90 | }; 91 | 92 | shocks 93 | { 94 | epsilon_A[]; 95 | }; 96 | 97 | calibration 98 | { 99 | delta = 0.035; 100 | alpha = 0.35; 101 | rho_A = 0.95; 102 | }; 103 | }; 104 | 105 | block EQUILIBRIUM 106 | { 107 | identities 108 | { 109 | Y[] = C[] + I[]; 110 | }; 111 | }; 112 | -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_firm_capital_comparison.gcn: -------------------------------------------------------------------------------- 1 | tryreduce 2 | { 3 | Pi[], U[], TC[]; 4 | }; 5 | 6 | block STEADYSTATE 7 | { 8 | definitions 9 | { 10 | # Capital/Labor Ratio 11 | N[ss] = (alpha * beta * A[ss] / (1 - beta * (1 - delta))) 12 | ^ (1 / (1 - alpha)); 13 | }; 14 | 15 | identities 16 | { 17 | A[ss] = 1; 18 | P[ss] = 1; 19 | Pi[ss] = 0; 20 | 21 | L[ss] = (1 - alpha) / Theta / (1 - delta * N[ss] ^ (1 - alpha)); 22 | K[ss] = N[ss] * L[ss]; 23 | 24 | r[ss] = 1 / beta - (1 - delta); 25 | w[ss] = (1 - alpha) * N[ss] ^ alpha; 26 | 27 | Y[ss] = A[ss] * K[ss] ^ alpha * L[ss] ^ (1 - alpha); 28 | I[ss] = delta * K[ss]; 29 | C[ss] = Y[ss] - I[ss]; 30 | 31 | U[ss] = (1 / (1 - beta)) * (log(C[ss]) - Theta * L[ss]); 32 | lambda[ss] = 1 / (C[ss] * P[ss]); 33 | TC[ss] = -(r[ss] * K[ss] + w[ss] * L[ss]); 34 | }; 35 | }; 36 | 37 | block HOUSEHOLD 38 | { 39 | definitions 40 | { 41 | u[] = log(C[]) - Theta * L[]; 42 | }; 43 | 44 | objective 45 | { 46 | U[] = u[] + beta * E[][U[1]]; 47 | }; 48 | 49 | controls 50 | { 51 | C[], L[], I[], K[]; 52 | }; 53 | 54 | constraints 55 | { 56 | C[] + I[] = w[] * L[] + r[] * K[-1] + Pi[] : lambda[]; 57 | K[] = (1 - delta) * K[-1] + I[]; 58 | }; 59 | 60 | calibration 61 | { 62 | beta = 0.99; 63 | Theta = 1; 64 | delta = 0.035; 65 | }; 66 | }; 67 | 68 | 69 | block FIRM 70 | { 71 | controls 72 | { 73 | K[-1], L[]; 74 | }; 75 | 76 | objective 77 | { 78 | TC[] = -(w[] * L[] + r[] * K[-1]); 79 | }; 80 | 81 | constraints 82 | { 83 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : P[]; 84 | }; 85 | 86 | identities 87 | { 88 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 89 | P[] = 1; 90 | Pi[] = P[] * Y[] + TC[]; 91 | }; 92 | 93 | shocks 94 | { 95 | epsilon_A[]; 96 | }; 97 | 98 | calibration 99 | { 100 | alpha = 0.35; 101 | rho_A = 0.95; 102 | }; 103 | }; 104 | -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_linearized.gcn: -------------------------------------------------------------------------------- 1 | options 2 | { 3 | linear = True; 4 | }; 5 | 6 | block STEADY_STATE 7 | { 8 | identities 9 | { 10 | A[ss] = 1; 11 | R[ss] = (1 / beta - (1 - delta)); 12 | W[ss] = (1 - alpha) ^ (1 / (1 - alpha)) * (alpha / R[ss]) ^ (alpha / (1 - alpha)); 13 | Y[ss] = (R[ss] / (R[ss] - delta * alpha)) ^ (sigma / (sigma + phi)) * 14 | ((1 - alpha) ^ (-phi) * (W[ss]) ^ (1 + phi)) ^ (1 / (sigma + phi)); 15 | K[ss] = alpha * Y[ss] / R[ss]; 16 | I[ss] = delta * K[ss]; 17 | C[ss] = Y[ss] - I[ss]; 18 | L[ss] = (1 - alpha) * Y[ss] / W[ss]; 19 | }; 20 | }; 21 | 22 | block SYSTEM_EQUATIONS 23 | { 24 | identities 25 | { 26 | #1. Labor supply 27 | W[] = sigma * C[] + phi * L[]; 28 | 29 | #2. Euler Equation 30 | sigma / beta * (E[][C[1]] - C[]) = R[ss] * E[][R[1]]; 31 | 32 | #3. Law of motion of capital 33 | K[] = (1 - delta) * K[-1] + delta * I[]; 34 | 35 | #4. Production Function 36 | Y[] = A[] + alpha * K[-1] + (1 - alpha) * L[]; 37 | 38 | #5. Demand for capital 39 | R[] = Y[] - K[-1]; 40 | 41 | #6. Demand for labor 42 | W[] = Y[] - L[]; 43 | 44 | #7. Equlibrium Condition 45 | Y[ss] * Y[] = C[ss] * C[] + I[ss] * I[]; 46 | 47 | #8. Productivity Shock 48 | A[] = rho_A * A[-1] + epsilon_A[]; 49 | }; 50 | 51 | shocks 52 | { 53 | epsilon_A[] ~ Normal(mu=0, sigma=sigma_A); 54 | }; 55 | 56 | calibration 57 | { 58 | sigma ~ maxent(Gamma(), lower=1.5, upper=3.0) = 2; 59 | phi ~ maxent(Gamma(), lower=1.0, upper=5.0) = 1.5; 60 | alpha ~ Beta(alpha=5, beta=9) = 0.35; 61 | beta ~ Beta(alpha=10, beta=1) = 0.985; 62 | delta ~ Beta(alpha=1, beta=10) = 0.025; 63 | rho_A ~ Beta(alpha=1, beta=5) = 0.95; 64 | sigma_A ~ maxent(Gamma(), lower=0.001, upper=0.1) = 0.01; 65 | }; 66 | 67 | }; 68 | -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_manually_calibrated.gcn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/Test GCNs/rbc_manually_calibrated.gcn -------------------------------------------------------------------------------- /tests/Test GCNs/rbc_with_excluded.gcn: -------------------------------------------------------------------------------- 1 | block HOUSEHOLD 2 | { 3 | definitions 4 | { 5 | u[] = C[] ^ (1 - sigma_C) / (1 - sigma_C) - 6 | L[] ^ (1 + sigma_L) / (1 + sigma_L); 7 | }; 8 | controls 9 | { 10 | K[], C[], L[], I[]; 11 | }; 12 | objective 13 | { 14 | U[] = u[] + beta * E[][U[1]]; 15 | }; 16 | constraints 17 | { 18 | @exclude 19 | C[] + I[] = w[] * L[] + r[] * K[-1] : lambda[]; 20 | 21 | K[] = (1 - delta) * K[-1] + I[] : q[]; 22 | }; 23 | 24 | calibration 25 | { 26 | beta = 0.985; 27 | delta = 0.025; 28 | sigma_C = 2; 29 | sigma_L = 1.5; 30 | }; 31 | }; 32 | 33 | 34 | block FIRM 35 | { 36 | controls 37 | { 38 | K[-1], L[]; 39 | }; 40 | 41 | objective 42 | { 43 | TC[] = -(w[] * L[] + r[] * K[-1]); 44 | }; 45 | 46 | constraints 47 | { 48 | Y[] = A[] * K[-1] ^ alpha * L[] ^ (1 - alpha) : P[]; 49 | }; 50 | 51 | identities 52 | { 53 | log(A[]) = rho_A * log(A[-1]) + epsilon_A[]; 54 | P[] = 1; 55 | }; 56 | 57 | shocks 58 | { 59 | epsilon_A[]; 60 | }; 61 | 62 | calibration 63 | { 64 | alpha = 0.35; 65 | rho_A = 0.95; 66 | }; 67 | }; 68 | 69 | block EQUILIBRIUM 70 | { 71 | constraints 72 | { 73 | Y[] = C[] + I[]; 74 | }; 75 | }; 76 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/__init__.py -------------------------------------------------------------------------------- /tests/dynare_outputs/basic_rbc_loglinear_results.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/dynare_outputs/basic_rbc_loglinear_results.mat -------------------------------------------------------------------------------- /tests/dynare_outputs/basic_rbc_results.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/dynare_outputs/basic_rbc_results.mat -------------------------------------------------------------------------------- /tests/dynare_outputs/full_nk_results.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/dynare_outputs/full_nk_results.mat -------------------------------------------------------------------------------- /tests/dynare_outputs/one_block_1_ss_results.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/dynare_outputs/one_block_1_ss_results.mat -------------------------------------------------------------------------------- /tests/dynare_outputs/rbc_2_block_ss_results.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/dynare_outputs/rbc_2_block_ss_results.mat -------------------------------------------------------------------------------- /tests/test_compile.py: -------------------------------------------------------------------------------- 1 | from typing import Literal 2 | 3 | import numpy as np 4 | import pytest 5 | import sympy as sp 6 | 7 | from gEconpy.model.compile import BACKENDS, compile_function 8 | 9 | 10 | @pytest.mark.parametrize("backend", ["numpy", "numba", "pytensor"]) 11 | def test_scalar_function(backend: Literal["numpy", "numba", "pytensor"]): 12 | x = sp.symbols("x") 13 | f = x**2 14 | f_func, _ = compile_function( 15 | [x], f, backend=backend, mode="FAST_COMPILE", pop_return=backend == "pytensor" 16 | ) 17 | assert f_func(x=2) == 4 18 | 19 | 20 | @pytest.mark.parametrize("backend", ["numpy", "numba", "pytensor"]) 21 | @pytest.mark.parametrize("stack_return", [True, False]) 22 | def test_multiple_outputs( 23 | backend: Literal["numpy", "numba", "pytensor"], stack_return: bool 24 | ): 25 | x, y, z = sp.symbols("x y z ") 26 | x2 = x**2 27 | y2 = y**2 28 | z2 = z**2 29 | f_func, _ = compile_function( 30 | [x, y, z], 31 | [x2, y2, z2], 32 | backend=backend, 33 | stack_return=stack_return, 34 | mode="FAST_COMPILE", 35 | ) 36 | res = f_func(x=2, y=3, z=4) 37 | assert ( 38 | isinstance(res, np.ndarray) if stack_return else isinstance(res, list | tuple) 39 | ) 40 | assert res.shape == (3,) if stack_return else len(res) == 3 41 | np.testing.assert_allclose( 42 | res if stack_return else np.stack(res), np.array([4.0, 9.0, 16.0]) 43 | ) 44 | 45 | 46 | @pytest.mark.parametrize("backend", ["numpy", "numba", "pytensor"]) 47 | def test_matrix_function(backend: Literal["numpy", "numba", "pytensor"]): 48 | x, y, z = sp.symbols("x y z") 49 | f = sp.Matrix([x, y, z]).reshape(1, 3) 50 | 51 | f_func, _ = compile_function( 52 | [x, y, z], 53 | f, 54 | backend=backend, 55 | mode="FAST_COMPILE", 56 | pop_return=backend == "pytensor", 57 | ) 58 | res = f_func(x=2, y=3, z=4) 59 | 60 | assert isinstance(res, np.ndarray) 61 | assert res.shape == (1, 3) 62 | np.testing.assert_allclose(res, np.array([[2.0, 3.0, 4.0]])) 63 | 64 | 65 | @pytest.mark.parametrize("backend", ["numpy", "numba", "pytensor"]) 66 | def test_compile_gradient(backend: BACKENDS): 67 | x, y, z = sp.symbols("x y z") 68 | f = x**2 + y**2 + z**2 69 | grad = sp.Matrix([f.diff(x), f.diff(y), f.diff(z)]).reshape(3, 1) 70 | grad_func, _ = compile_function( 71 | [x, y, z], 72 | grad, 73 | backend=backend, 74 | mode="FAST_COMPILE", 75 | pop_return=backend == "pytensor", 76 | ) 77 | res = grad_func(x=2.0, y=3.0, z=4.0) 78 | np.testing.assert_allclose(res, np.array([4.0, 6.0, 8.0])[:, None]) 79 | 80 | hess = grad.jacobian([x, y, z]) 81 | hess_func, _ = compile_function( 82 | [x, y, z], 83 | hess, 84 | backend=backend, 85 | mode="FAST_COMPILE", 86 | pop_return=backend == "pytensor", 87 | ) 88 | res = hess_func(x=2.0, y=3.0, z=4.0) 89 | np.testing.assert_allclose(res, np.eye(3) * 2.0) 90 | -------------------------------------------------------------------------------- /tests/test_statespace.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pymc as pm 3 | import pytensor 4 | import pytest 5 | 6 | from tests.utilities.shared_fixtures import ( 7 | load_and_cache_model, 8 | load_and_cache_statespace, 9 | ) 10 | 11 | 12 | @pytest.mark.parametrize( 13 | "gcn_file", 14 | [ 15 | "one_block_1_ss.gcn", 16 | "open_rbc.gcn", 17 | "full_nk.gcn", 18 | "rbc_linearized.gcn", 19 | ], 20 | ) 21 | def test_statespace_matrices_agree_with_model(gcn_file): 22 | ss_mod = load_and_cache_statespace(gcn_file) 23 | model = load_and_cache_model(gcn_file, "numpy", use_jax=False) 24 | 25 | inputs = pm.inputvars(ss_mod.linearized_system) 26 | input_names = [x.name for x in inputs] 27 | f = pytensor.function(inputs, ss_mod.linearized_system, on_unused_input="ignore") 28 | mod_matrices = model.linearize_model( 29 | verbose=False, steady_state_kwargs={"verbose": False, "progressbar": False} 30 | ) 31 | 32 | param_dict = model.parameters() 33 | ss_matrices = f(**{k: param_dict[k] for k in input_names}) 34 | 35 | for mod_matrix, ss_matrix in zip(mod_matrices, ss_matrices): 36 | np.testing.assert_allclose(mod_matrix, ss_matrix, atol=1e-8, rtol=1e-8) 37 | 38 | 39 | @pytest.mark.parametrize( 40 | "gcn_file", 41 | [ 42 | "one_block_1_ss.gcn", 43 | "open_rbc.gcn", 44 | "full_nk.gcn", 45 | "rbc_linearized.gcn", 46 | ], 47 | ) 48 | def test_model_to_pymc(gcn_file): 49 | ss_mod = load_and_cache_statespace(gcn_file) 50 | with pm.Model() as m: 51 | ss_mod.to_pymc() 52 | rv_names = [rv.name for rv in m.free_RVs] 53 | 54 | assert all(name in rv_names for name in ss_mod.param_priors.keys()) 55 | 56 | hyper_prior_names = [ 57 | name 58 | for dist in ss_mod.shock_priors.values() 59 | for name in dist.param_name_to_hyper_name.values() 60 | ] 61 | 62 | assert all(name in rv_names for name in hyper_prior_names) 63 | 64 | 65 | @pytest.mark.parametrize( 66 | "gcn_file", 67 | [ 68 | "one_block_1_ss.gcn", 69 | "open_rbc.gcn", 70 | "full_nk.gcn", 71 | "rbc_linearized.gcn", 72 | ], 73 | ) 74 | def test_model_config(gcn_file): 75 | ss_mod = load_and_cache_statespace(gcn_file) 76 | -------------------------------------------------------------------------------- /tests/test_time_aware_symbols.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import sympy as sp 4 | 5 | from gEconpy.classes.time_aware_symbol import TimeAwareSymbol 6 | from gEconpy.utilities import ( 7 | diff_through_time, 8 | step_equation_backward, 9 | step_equation_forward, 10 | ) 11 | 12 | 13 | class TimeAwareSymbolTests(unittest.TestCase): 14 | def setUp(self): 15 | self.x_t = TimeAwareSymbol("x", 0) 16 | self.x_tp1 = TimeAwareSymbol("x", 1) 17 | self.x_tm1 = TimeAwareSymbol("x", -1) 18 | 19 | def test_base_name(self): 20 | self.assertEqual("x", self.x_t.base_name) 21 | 22 | def test_time_index(self): 23 | self.assertEqual(0, self.x_t.time_index) 24 | 25 | def test_step_forward(self): 26 | x_t1 = self.x_t.step_forward() 27 | self.assertEqual("x", x_t1.base_name) 28 | self.assertEqual("x_t+1", x_t1.name) 29 | self.assertEqual(1, x_t1.time_index) 30 | 31 | def test_step_backward(self): 32 | x_tm1 = self.x_t.step_backward() 33 | self.assertEqual("x", x_tm1.base_name) 34 | self.assertEqual("x_t-1", x_tm1.name) 35 | self.assertEqual(-1, x_tm1.time_index) 36 | 37 | def test_steady_state(self): 38 | x_ss = self.x_t.to_ss() 39 | self.assertEqual("x", x_ss.base_name) 40 | self.assertEqual("x_ss", x_ss.name) 41 | self.assertEqual("ss", x_ss.time_index) 42 | 43 | def test_equality_after_stepping(self): 44 | self.assertEqual(self.x_t.step_forward(), self.x_tp1) 45 | self.assertEqual(self.x_t.step_backward(), self.x_tm1) 46 | self.assertEqual(self.x_tp1.to_ss(), self.x_tm1.to_ss()) 47 | 48 | def test_step_equation_backward(self): 49 | eq = self.x_t + self.x_tp1 + self.x_tm1 50 | self.assertEqual( 51 | step_equation_backward(eq), self.x_tm1 + self.x_t + TimeAwareSymbol("x", -2) 52 | ) 53 | 54 | def test_step_equation_forward(self): 55 | eq = self.x_t + self.x_tp1 + self.x_tm1 56 | self.assertEqual( 57 | step_equation_forward(eq), self.x_tp1 + TimeAwareSymbol("x", 2) + self.x_t 58 | ) 59 | 60 | def test_diff_through_time(self): 61 | # X = Sum_{t=0}^10 beta * x_t 62 | # If we have 10 FoC for each x_t, then the Lagrangian is: 63 | # dL/dx_t = Sum_{t=0}^10 beta ** t 64 | 65 | X = sum(TimeAwareSymbol("x", t) for t in range(-10, 10)) 66 | dX_dx_t = diff_through_time(X, self.x_t, sp.Symbol("beta")) 67 | 68 | self.assertEqual(dX_dx_t, sum(sp.Symbol("beta") ** t for t in range(11))) 69 | 70 | 71 | if __name__ == "__main__": 72 | unittest.main() 73 | -------------------------------------------------------------------------------- /tests/utilities/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessegrabowski/gEconpy/7e044e201776f2e6916eac97cda6b1cc354fa2da/tests/utilities/__init__.py -------------------------------------------------------------------------------- /tests/utilities/load_dynare.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from collections.abc import Sequence 4 | 5 | import numpy as np 6 | import pandas as pd 7 | import scipy.io as sio 8 | 9 | 10 | def squeeze_record(x): 11 | if hasattr(x, "__len__") and len(x) == 1: 12 | try: 13 | return squeeze_record(x[0]) 14 | except (IndexError, TypeError): 15 | pass 16 | return x 17 | 18 | 19 | def record_to_dict(x): 20 | if x.dtype.names is not None: 21 | return dict(zip(x.dtype.names, x)) 22 | return x 23 | 24 | 25 | def get_available_models(): 26 | dynare_output_dir = "tests/dynare_outputs" 27 | mat_files = os.listdir(dynare_output_dir) 28 | models = [x.replace("_results.mat", "") for x in mat_files] 29 | return { 30 | model: os.path.join(dynare_output_dir, fname) 31 | for model, fname in zip(models, mat_files) 32 | } 33 | 34 | 35 | def read_dynare_output( 36 | model_name, 37 | ) -> tuple[dict[str, np.ndarray], dict[str, np.ndarray]]: 38 | models = get_available_models() 39 | path = models[model_name] 40 | 41 | dynare_data = sio.loadmat(path) 42 | 43 | oo = record_to_dict(squeeze_record(dynare_data["oo_"])) 44 | for key, value in oo.items(): 45 | oo[key] = record_to_dict(squeeze_record(value)) 46 | 47 | M = record_to_dict(squeeze_record(dynare_data["M_"])) 48 | for k, v in M.items(): 49 | M[k] = squeeze_record(v) 50 | 51 | return oo, M 52 | 53 | 54 | def extract_policy_matrices(oo, M) -> tuple[pd.DataFrame, pd.DataFrame]: 55 | var_names = np.concatenate([x.item() for x in M["endo_names"]]) 56 | shock_names = np.concatenate( 57 | [np.atleast_1d(x.item()) for x in np.atleast_1d(M["exo_names"])] 58 | ) 59 | state_idx = M["state_var"] - 1 60 | dynare_order = oo["dr"]["order_var"].ravel() - 1 61 | 62 | dr_state_idx = np.array([x for x in dynare_order if x in state_idx]) 63 | 64 | dynare_T = pd.DataFrame( 65 | oo["dr"]["ghx"], index=var_names[dynare_order], columns=var_names[dr_state_idx] 66 | ) 67 | dynare_R = pd.DataFrame( 68 | oo["dr"]["ghu"], index=var_names[dynare_order], columns=shock_names 69 | ) 70 | 71 | return dynare_T, dynare_R 72 | 73 | 74 | def load_dynare_outputs(model_name) -> dict[str, pd.DataFrame]: 75 | models = get_available_models() 76 | if model_name not in models: 77 | raise ValueError( 78 | f"Model {model_name} not found. Available models are {models.keys()}" 79 | ) 80 | 81 | oo, M = read_dynare_output(model_name) 82 | T, R = extract_policy_matrices(oo, M) 83 | 84 | return {"T": T, "R": R} 85 | -------------------------------------------------------------------------------- /tests/utilities/shared_fixtures.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from functools import cache 4 | 5 | from gEconpy import model_from_gcn, statespace_from_gcn 6 | 7 | 8 | @cache 9 | def load_and_cache_model(gcn_file, backend, use_jax=False): 10 | compile_kwargs = {} 11 | if backend == "pytensor" and use_jax: 12 | compile_kwargs["mode"] = "JAX" 13 | 14 | gcn_path = os.path.join("tests", "Test GCNs", gcn_file) 15 | model = model_from_gcn( 16 | gcn_path, 17 | verbose=False, 18 | backend=backend, 19 | **compile_kwargs, 20 | ) 21 | 22 | return model 23 | 24 | 25 | @cache 26 | def load_and_cache_statespace(gcn_file): 27 | gcn_path = os.path.join("tests", "Test GCNs", gcn_file) 28 | statespace = statespace_from_gcn(gcn_path, verbose=False) 29 | 30 | return statespace 31 | --------------------------------------------------------------------------------