PYPI 6.3.0 · OPEN SOURCE · MIT LICENSE · PYTHON 3.11+
Macroeconometrics and structural modeling in Python.
Analyze macroeconomic data, simulate policy, and export results with NumPy, SciPy, pandas and Matplotlib. A local workstation is the supported target; browser and tablet workflows are best effort.
pip install puremacro

CI
tests across three operating systems and Python 3.11–3.13
Examples
worked analyses, simulations and empirical replications
EN / ES
notebook learning paths in English and Spanish
0
compiled extensions of its own: pure Python on NumPy and SciPy
Releases and capabilities · Gallery · From Stata & Dynare · Run it anywhere · Documentation · Changelog
RELEASE STATUS · PUREMACRO 6.3.0
Research APIs for models and inference
The published package is 6.3.0. It adds equilibrium derivatives and continuation, simulation-aware SMM, identification-robust confidence sets, and bounded models of trade reallocation, heterogeneous expectations, sovereign banking and adaptation. The research API guide explains ownership, validation and composition contracts. See the release notes and validation and changelog.
The DSGE guides also cover ordered model commands, continuation, announcements and constrained transitions, and local/global accuracy, with runnable examples and explicit compatibility limits. Dynare support remains a documented subset. Residual and refinement checks provide finite numerical evidence; they do not establish global existence, uniqueness or economic validity. See the release validation and known accuracy issues. Also included: DP model files, reproducible studies and editable HANK equations.
Experimental second-order HANK adds state curvature, anticipated-risk terms and pruned simulation for small full-basis one-asset models. Independent nonlinear audits retain rejected shock cases. The benchmark does not establish grid convergence, global or infinite-horizon accuracy, welfare, or two-asset support. English and Spanish guides document the supported domain and numerical limits.
The bilingual course edition course-2026A-5.5.0 pins puremacro==5.5.0 and requires Python 3.12+. All 72 notebooks were executed against the recorded candidate wheel with frozen data and cached language-model responses, including the required DP and text sections. The release record verifies that the published wheel contains the same runtime files. Optional live-data and live-model paths were not part of that validation. The library itself continues to support Python 3.11+.
Updated DSGE lessons · 23 October 2026. T02_A–D in English and Spanish pin their code, helpers and models to v5.7.1. All eight notebooks completed a fresh local Python execution: 120 code cells and 72 figures. They cover equation stacking, nonlinear transitions, stochastic Euler equations, local/global policy comparisons, irreversible investment and stochastic volatility. Open the notebooks and setup guide · Execution evidence. This evidence does not certify a full Colab, Juno or browser notebook run.
HOUSEHOLD MODELING · AVAILABLE SINCE 5.1
Heterogeneous-agent models, declared like a .mod file
The examples below were prepared for 5.1 and remain illustrations of the published household-modeling workflow. Their figures come from notebook 21, the dp guide and the SCF example. Use the documented package and course edition for each notebook; the numerical values in these figures belong to the examples shown.
DECLARATIVE DYNAMIC PROGRAMMING · NOTEBOOK 21
Declare the model, read its exact distribution, simulate a panel
puremacro.dp does for dynamic programs what a Dynare .mod file does for DSGE models: states, shocks, choices, the reward and the constraints are equations in Dynare expression syntax, parsed by the same parser, and Model.solve() writes the solver call. Inequality statistics come exactly from the stationary distribution. In the published 6.3.0 package, simulate supports VFI and EGM panels, continuous-time HJB and Krusell–Smith simulation within their documented model restrictions, with seeded reproducibility. See the simulation guide for the supported modes. dp is the supported interface for declaring these models.
dp.Model, DPSolution.gini, DPSolution.lorenz, DPSolution.simulate, dp.Panel
Open notebook 21 in your browser →

dp: mean assets 6.5733 and a wealth Gini of 0.3494, both exact. A simulated panel that starts everyone at a = 0.1 overshoots to 0.4449 at t = 10 and settles at 0.3496 by t = 199.ONE DECLARATION, SEVERAL SOLVERS
Life cycles, discrete choices and aggregate risk in the same syntax
solve() compiles a declaration to discrete value function iteration, to the endogenous grid method (one step per age in a life cycle, an upper envelope over a discrete choice, logit choice probabilities with taste shocks), to the continuous-time HJB solver when the model has a drift, or to the Krusell–Smith forecast-rule loop under aggregate risk. Supported equilibrium configurations declare prices and market clearing in the same syntax; each solver has explicit model restrictions.
Model.horizon, Model.discrete, Model.taste_shocks, Model.aggregate_state, Model.solve("egm")
Read the dp guide →

dp guide, solved by EGM: a life cycle whose mean assets peak at retirement (age 45), a work-or-not choice with taste shocks (participation 63.3%), and a Krusell–Smith economy whose forecast rule converges in 8 rounds with R² of 0.99996.SURVEY MICRODATA
Household surveys with design-based standard errors
fetch.micro reads ACS, CPS, SCF and ENIGH data into a MicroFrame that records the available survey design. Supported uncertainty estimates use ACS/SCF replicate weights or ENIGH strata and PSUs; the CPS basic reader carries weights only. Not every statistic has design-based uncertainty for every source. A worked SCF–Aiyagari example shows what a calibrated model explains and misses.
fetch.micro.fetch_scf, MicroFrame.gini, MicroFrame.top_share, fetch.registry
Read the microdata guide →

Also in 5.1: puremacro.llm, one entry point for local language models (MLX, llama.cpp, Ollama and OpenAI-compatible servers) with a completion cache that any engine can answer from; puremacro.text, a tokenizer and sparse document-term matrix for narrative corpora that are now stored and exportable; exact-diffuse Kalman filtering and smoothing that agree with the batch posterior; the full Stock–Yogo tables; and Galí’s (1999) difference specification in the benchmark example. Full changelog.
CROSS-COUNTRY DATA
Cross-country data in one call, with every seam recorded
One-call panels from the World Bank, the OECD, Eurostat, the IMF, the BIS, ILOSTAT, the Penn World Table and the Maddison Project, each a (code, date) frame that carries its units, sources and what it could not obtain, and splice_sources to join them into long series with every seam recorded. These data tools remain available in the published 6.3.0 package.
UPGRADING FROM 4.8
- Trade and MRIO returned in 5.2.0. The legacy accounting, bundled table and named scenarios were removed; migrate 4.x applications using the 5.2 migration notes. Results can change under the corrected accounting. The course edition
course-2026A-5.5.0pins 5.5.0 and requires Python 3.12+; follow its setup instructions. - The research studies added since 4.4 left the package as well: the SW07 estimator studies, the household incidence application and the cross-country forecasting application.
puremacro.structuraland the Romer–Romer (2010) replication stay. vfi.Modelis deprecated and will be removed in 6.0; declare the model withpuremacro.dp.vfi.simulate_panelnow refuses a policy that is not an integer array of grid indices; useDPSolution.simulate.kalman_filterandkalman_smootherwithdiffuse_statesreturn the exact diffuse results, sologlikchanges whenever a diffuse loading is not one.PUREMACRO_LLM_CACHEnow names the completion cache ofpuremacro.llm; the narrative score cache moved toPUREMACRO_LLM_SCORES_CACHE, and the local narrative backends default toqwen3-4b.
LATEST RELEASES · UPDATED AUTOMATICALLY
- puremacro 6.4.0 adds reusable own-data quarterly fiscal policy briefs, bounded connector provenance and freshness reporting, local-projection chronological and specification contracts with two-way fixed-effects panel IV, and eleven numerical and data-provenance correctness fixes […]
- puremacro 6.3.0 adds research APIs for solving equilibria, accounting for simulation uncertainty, and auditing policy models. It merges #232 and #233 while preserving existing entry points and their approximation orders. Equilibrium derivatives, […]
- Fiscal rules & debt-sustainability analysis, state-dependent LP & weak-IV HAC diagnostics, sequence-space optimal policy, SVAR identification, GIV, and investment-research workflows. Added Experimental investment-research kernels in asset_pricing: lagged, self-financing long-only backtests with cash, […]
From the GitHub release feed. All releases · Changelog · PyPI history
Why puremacro
Built at ITAM–CIE for applied analysis, research and teaching, with explicit numerical diagnostics and reproducible examples.
PURE PYTHON
No compiler, no licence
The numerical core uses NumPy, SciPy, pandas and Matplotlib, with no compiled extension of its own. Data fetching also uses requests; optional workflows have additional dependencies. Frozen reference comparisons run in Python; regenerating external reference output can require the original software.
RUNS ANYWHERE
Laptop, browser, iPad
Local installation is supported. The numerical core is Pyodide-compatible, while browser and tablet execution depends on memory, file formats and network access. Colab helpers package heavier jobs; checkpointed workflows can resume supported computations.
SPEAKS DYNARE
Bring your .mod files
Compile the supported Dynare subset, choose local orders 1–3 or nonlinear perfect foresight, and inspect explicit compatibility and accuracy reports. Existing pruning, OccBin and oo_.dr interfaces remain available.
PUBLICATION-READY
From estimate to LaTeX
Estimators return result objects with .summary(), .plot() and .to_latex(), so the last step to a paper table is one line.
What it can do
The empirical and structural toolkit of modern macroeconomics, in one library.
VARs & identification
Cholesky, long-run, sign and zero, narrative, proxy-IV, heteroskedasticity and non-Gaussian identification, with bootstrap and Bayesian bands.
Local projections & inference
LP-HAC, LP-IV, lag-augmented, panel, state-dependent, smooth and quantile LPs, with HAC, fixed-b and weak-IV-robust inference.
DSGE & Bayesian estimation
Shared nonlinear equations, local perturbation and pruning, deterministic transitions, explicitly mapped global policies, OccBin and Bayesian estimation. Off-grid Euler/KKT audits and solver-specific diagnostics expose numerical limits; likelihood-score support depends on the estimation specification.
Heterogeneous agents
Models declared as equations with puremacro.dp and solved by VFI, EGM, continuous-time HJB or Krusell–Smith; sequence-space HANK with the Fake News algorithm; firm dynamics and neural-network solvers.
Microdata, space & climate
ACS, CPS, SCF and ENIGH readers with their available survey designs, spatial models and climate scenarios. Trade and MRIO returned in 5.2 with consistent accounting, rebuilt OECD data and household incidence conditional on supplied prices and incomes.
Data, nowcasting & forecasting
One-call cross-country panels from the World Bank, OECD, Eurostat, IMF, BIS, ILOSTAT, PWT and Maddison; FRED, ECB, Banxico and INEGI fetchers; real-time vintages, nowcasts, text-based uncertainty indices and BVAR fan charts.
A REAL EXAMPLE
From live data to a local projection
Pull U.S. real GDP and the federal funds rate from FRED, estimate a local projection with 90% Newey–West bands, and plot it. This example uses the policy-rate level, not an identified policy shock: it illustrates an association, not a causal monetary-policy effect.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from puremacro.fetch import fetch_fred
from puremacro.lp.jorda import lp_hac
gdp = fetch_fred("GDPC1").dropna().resample("QS").last()
ff = fetch_fred("FEDFUNDS").dropna().resample("QS").mean()
df = pd.concat([np.log(gdp).rename("log_gdp"),
ff.rename("ff")], axis=1).dropna()
irf = lp_hac(df, y="log_gdp", x="ff",
horizons=range(0, 17), n_lags=2, alpha=0.10)
plt.plot(irf["h"], irf["beta"])
plt.fill_between(irf["h"], irf["lo"], irf["hi"], alpha=0.15)
Replication examples and independent evidence
Bundled empirical examples use frozen data snapshots. The replication scorecard distinguishes internal regression references from published targets; a separate research-benchmark dossier records analytical and external-software comparisons and their limitations.



from puremacro.replication import scorecard
df = scorecard() # inspect each row's reference and scope
df["passed"].all()
Read each case’s source, specification and tolerance before interpreting a pass. Internal regression checks are not published replications. The independent research dossier retains a known RR2010 published t-statistic rounding mismatch; matching software output does not make that comparison pass.
Coming from Stata, MATLAB or Dynare?
The commands you know, and their puremacro equivalents.
| Task | Stata / MATLAB / Dynare | puremacro |
|---|---|---|
| Cholesky SVAR | var y1 y2, lags(1/4) + irf create | var.identify.cholesky_svar(Y, p=4, horizon=20) |
| Local Projections (HAC) | jorda / manual OLS | lp.lp_hac(df, y="y", x="shock", horizon=20, lags=4) |
| Staggered DiD | csdid y, ivar(id) time(t) gvar(g) | did.callaway_santanna(df, unit="id", time="t", outcome="y", treat_time="g") |
| DSGE from equations / .mod | Dynare .mod file | dsge.load_mod("rbc.mod") / dsge.build_dynare(eqs) |
| Bayesian DSGE (MCMC) | Dynare estimation(...) (Metropolis-Hastings) | dsge.estimate_dsge_bayesian(m, data, priors, n_draws=10000) |
| Spatial Gravity GE | Allen-Arkolakis replication | spatial.AllenArkolakisModel.from_coordinates(...) |
TABLET WORKFLOWS · BEST EFFORT
Macroeconomics on an iPad, with Juno
Tablet workflows depend on the app’s Python version, available packages, memory and file access. A local workstation remains the supported installation target. Use the runtime guide to check the numerical core in Juno or a Pyodide browser session.
- Knows where it is. puremacro recognises Juno, both its built-in Python and its in-browser Pyodide kernel, and works inside the iPad’s sandboxed file system.
- Brings its data. Pocket cartridges carry panels built on your workstation to the iPad, checked on arrival, even in airplane mode.
- Survives interruptions. Supported checkpointed computations can resume from saved state. Checkpointing must be enabled, and it does not make every estimator or interrupted tablet session resumable.
- Knows its limits.
runtime.fitsizes bootstraps to the device, and heavy jobs offload to Google Colab as a single notebook.
# In Juno, with puremacro installed
from puremacro import runtime
# What can this iPad do?
print(runtime.report())
# Size the bootstrap to the device
print(runtime.fit(n_boot=2000))
Detection and budgets are opt-in: the same script gives the same numbers on your laptop.
ENGINEERED FOR CORRECTNESS
Numbers you can defend
Research code has to be right before it is fast. puremacro treats correctness as a feature.
- CI runs the default suite on three operating systems and Python 3.11–3.13, plus the Pyodide import contract and documentation checks. PyPI publication waits for the release workflow’s required CI and opt-in tests.
- The validation gallery distinguishes internal, analytical, package and published-reference evidence. Each comparison has a specific scope and tolerance.
- The replication scorecard labels its reference types. A green test suite or converged solver does not certify every economic conclusion; inspect the independent research benchmarks and structural validation status.
- Clear diagnostic errors instead of silent garbage: singular matrices, non-positive-definite covariances and Blanchard–Kahn violations say what went wrong and where.
- Any released version that returned a wrong number is listed in a public correctness advisory.
Choose a question and a tested environment
Start with the quickstart on a local Python installation, or try a compatible notebook in the browser. Use the notebook learning paths for analysis and policy questions; the pinned 5.5.0 course edition has its own Python 3.12+ setup instructions.
CITE PUREMACRO
@software{alonso_ortiz_puremacro,
author = {Alonso Ortiz, Jorge},
title = {puremacro: Macroeconometrics and Structural Modeling in Python},
version = {6.3.0},
year = {2026},
url = {https://github.com/jalonso1979/puremacro}
}
Cite the version used in your analysis. This example names the published 6.3.0 package; use its release citation metadata when appropriate.

