Skip to content

pablo-reyes8/PyDSGEforge

Repository files navigation

PyDSGEforge

A general, YAML-first DSGE solver and Bayesian estimation toolkit implemented in Python.

CI Python 3.10+ License: MIT Status: research alpha Cite software Docker

Symbolic equations → rational-expectations solution → Kalman likelihood → MAP/MCMC → posterior diagnostics and IRFs.

Index

Dynare parity

The first benchmark is deliberately direct: the same three-equation New Keynesian model, 82 observations, priors, posterior mode, prefiltering, stationary Kalman initialization, and unit-shock convention are evaluated in Dynare/Octave and PyDSGEforge.

Numerical check Dynare PyDSGEforge Absolute difference
Log likelihood at Dynare mode -555.4646535601 -555.4646535592 9.14 × 10⁻¹⁰
Log posterior at Dynare mode -586.7712107416 -586.7712107406 9.14 × 10⁻¹⁰
Log posterior on 25 Dynare draws 1.82 × 10⁻⁹ max
Unit-shock IRFs 7.77 × 10⁻¹⁶ max

The curves below compare 500 retained Dynare draws with 10,500 post-warmup PyDSGEforge draws. Finite-chain KDEs need not overlap pixel-for-pixel; the pointwise likelihood and posterior checks above establish numerical parity.

Dynare and PyDSGEforge posterior distributions

Dynare and PyDSGEforge impulse responses

The compact, reviewable reference is in dynare_comprobation/. It contains the .mod file, readable CSV data, posterior mode, retained draws, metrics, and an independent validator—not Dynare's generated matrices, bytecode, or plots.

python dynare_comprobation/validate.py

Realistic DSGE showcases

Two larger YAML-only models demonstrate persistent states, forward and backward dynamics, measurement error, MAP estimation, adaptive Metropolis-Hastings, and posterior IRF bands.

Model Economic ingredients Solved system MCMC acceptance
HybridNKMedium Habit, indexation, rate smoothing, three AR(1) shocks 8 states, 3 shocks 20.5%
SmallOpenEconomyNK Hybrid IS/Phillips blocks, exchange rate, natural rate, open-economy Taylor rule 9 states, 4 shocks 23.8%

Hybrid medium-scale NK

Hybrid medium-scale NK posterior impulse responses

Small open-economy NK

Small open-economy NK posterior impulse responses

The synthetic datasets use fixed seeds and each model's solved state space. Rebuild the CSVs, estimations, posterior draws, PNG/PDF figures, and metrics with:

python scripts/build_showcase.py

Machine-readable results live in outputs/showcase_report.json. Notebook-ready cells for both models are in notebooks/showcase_more_models.ipynb.

Bayesian diagnostics, not just estimates

PyDSGEforge goes beyond producing a posterior mode or a collection of MCMC draws. Its analysis layer turns the retained chain into a detailed assessment of posterior uncertainty and sampling quality, directly in the economic parameter space.

  • Effective sample size (ESS): estimates how much independent information remains after accounting for serial correlation in the chain.
  • Monte Carlo precision: reports integrated autocorrelation time and Monte Carlo standard error (MCSE) for each selected parameter.
  • Credible regions: computes configurable highest posterior density intervals (HPDI), together with posterior mean, median, and standard deviation.
  • Visual convergence checks: produces trace plots, running means, posterior densities, and HPDI overlays, complemented by the sampler acceptance rate and explicit burn-in accounting.
  • Economic interpretation: compares prior and posterior distributions and propagates parameter uncertainty into posterior impulse-response bands.

The diagnostics are available from the same fitted model object:

diagnostics = model.analyze_posteriors(
    subset=["beta", "kappa", "phi_pi"],
    plot=True,
    describe=True,
    return_data=True,
)

This makes estimation, uncertainty quantification, sampling diagnostics, and economic interpretation part of one reproducible workflow rather than separate post-processing steps.

Why PyDSGEforge

  • General equations: declare variables, leads, lags, shocks, measurement equations, and parameters instead of selecting a hard-coded macro model.
  • YAML-first experiments: model structure, priors, bounds, data, solver, likelihood, MAP, MCMC, and IRF settings can live in one reviewable file.
  • Explicit numerical conventions: parameter transformations, covariance construction, Kalman initialization, prefiltering, and shock scaling are configurable and documented.
  • Composable Python API: use the high-level DSGE facade or the underlying builders, Gensys solver, inference, and analysis modules independently.
  • External validation: numerical comparisons are stored as fixtures and executable checks rather than screenshots alone.

Current capabilities include symbolic linearization with SymPy, Blanchard-Kahn checks, a Sims-style Gensys solution, Gaussian state-space likelihood, multiple prior families and constrained transformations, MAP optimization, adaptive Metropolis-Hastings, and posterior impulse-response summaries.

Installation

Python 3.10 or newer is required.

git clone https://github.com/pablo-reyes8/PyDSGEforge.git
cd PyDSGEforge
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
python -m pip install -e .

Development tools and optional Kalman-loop acceleration:

python -m pip install -e ".[dev]"
python -m pip install -e ".[speed]"

Quick start

Validate a configuration without estimating it:

python scripts/run_pipeline.py --config configs/nk_full_yaml.yaml --dry-run

Run the configured estimation:

python scripts/run_pipeline.py --config configs/nk_full_yaml.yaml

Use the same model from Jupyter:

from pathlib import Path

import pandas as pd
import yaml

from src.dsge import DSGE

config_path = Path("configs/hybrid_nk_medium.yaml")
cfg = yaml.safe_load(config_path.read_text(encoding="utf-8"))
model, registry, theta = DSGE.from_yaml(config_path)
data = pd.read_csv(cfg["data"]["path"])[cfg["data"]["columns"]].to_numpy()

result = model.compute(
    registry=registry,
    theta_struct=theta,
    data=data,
    compute_steady=False,
    div=cfg["solver"]["div"],
    map=cfg["map"]["enabled"],
    map_bounds="auto",
    map_kwargs={
        "method": cfg["map"]["method"],
        "hess_step": cfg["map"]["hess_step"],
        "tau_scale": cfg["map"]["tau_scale"],
        "hessian_strategy": cfg["map"]["hessian_strategy"],
        "include_jacobian_prior": cfg["map"]["include_jacobian_prior"],
    },
    run_mcmc=cfg["mcmc"]["enabled"],
    mcmc_draws=cfg["mcmc"]["draws"],
    mcmc_kwargs=cfg["mcmc"],
)

See docs/usage.md for the Python API and docs/yaml_configuration.md for the full schema.

YAML model specification

A model is expressed as economic equations—not precomputed matrices:

model:
  name: BasicNK
  variables:
    states: [x_t, pi_t, i_t]
    leads: [x_tp1, pi_tp1]
    shocks: [eps_d, eps_s, eps_m]
  equations:
    - "x_t = x_tp1 - (1 / sigma) * (i_t - pi_tp1) + eps_d"
    - "pi_t = beta * pi_tp1 + kappa * x_t + eps_s"
    - "i_t = phi_pi * pi_t + phi_x * x_t + eps_m"

parameters:
  specs:
    beta:
      transform: logistic
      bounds: {lower: 0.90, upper: 0.999}
      prior:
        family: beta
        params: {a: 391.05, b: 3.95, loc: 0.0, scale: 1.0}
  theta_econ:
    beta: 0.99

q:
  diag_params: [sig_d, sig_s, sig_m]

The complete benchmark is configs/nk_full_yaml.yaml; the smallest smoke test is configs/tiny_ar1.yaml.

Project structure

PyDSGEforge/
├── src/                    # Library: builders, solver, inference, analysis
├── configs/                # Reusable YAML model specifications
├── tests/                  # Numerical and API regression tests
├── docs/                   # Usage, schema, conventions, and testing notes
├── scripts/                # CLI, showcase, and reference export utilities
├── dynare_comprobation/    # Minimal external parity fixture
├── data/                   # Example and fixed-seed synthetic datasets
├── outputs/                # Reproducible figures and machine-readable results
└── notebooks/              # Interactive demonstrations

The core path is:

equations + parameter registry
        ↓
linear-system builder
        ↓
Gensys / Blanchard-Kahn solution
        ↓
state-space + Kalman likelihood
        ↓
MAP / MCMC
        ↓
posterior diagnostics + IRFs

Detailed module notes are available in docs/api.md and docs/numerical-conventions.md.

Reproducibility and quality

The repository provides one-command development gates:

make help          # list commands
make test          # unit and regression tests
make dynare-check  # independent numerical parity check
make check         # lint + tests + parity + package build
make docker-test   # isolated container test stage

CI tests Python 3.10–3.12, validates a configured model, checks the Dynare fixture, builds source/wheel distributions, installs the wheel, and executes the Docker test stage. The runtime container is multi-stage and runs as a non-root user.

Contributing, security, and citation

PyDSGEforge is released under the MIT License.

Roadmap

  • Add more cross-implementation fixtures and period-by-period Kalman diagnostics.
  • Extend nonlinear steady-state and higher-order approximation workflows.
  • Stabilize the public API and publish versioned documentation and packages.
  • Expand diagnostics for convergence, identification, and posterior predictive checks.

References

  • Sims, C. A. (2001). “Solving Linear Rational Expectations Models.” Computational Economics, 20, 1–20. doi:10.1023/A:1013825826056.
  • Jacobo, J. (2025). Una introducción a los métodos de máxima entropía y de inferencia bayesiana en econometría. Universidad Externado de Colombia.

License

This project is licensed under the MIT License — you are free to use, modify, and distribute this code, provided that appropriate credit is given to the author.

About

DSGEFoundry delivers a Dynare-inspired, fully Python workflow for building, solving, and estimating linearized DSGE models. Symbolic definitions turn into state-space systems, solved via Gensys, then pushed through Bayesian inference and IRF analytics with reusable abstractions.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors