Composing the research APIs
The research modules expose separate numerical and economic contracts. The table below gives the public entry points for the nine initial research slices. Imports through each parent package and the listed module refer to the same objects. Existing model-specific interfaces remain available.
| Purpose | Public module and entry point | Acceptance means |
|---|---|---|
| Local equilibrium derivatives | core.linearize_equilibrium; vfi.linearize_projection, vfi.linearize_aiyagari |
sensitivity().valid: regular retained equations and tested stencils |
| Branch continuation | core.continue_equilibrium |
Inspect termination status, rejected attempts and individual fold statuses |
| Simulation-aware estimation | structural.fit_simulated_moments |
success concerns optimization; inference_valid additionally checks local inference |
| Identification-robust inference | structural.simulated_moment_test, invert_quadratic_moments, evaluate_moment_grid |
A point test's accepted=None means unresolved; sampled grids never certify their interiors |
| HANK scalability | models.solve_hank_reduced_policy |
First-order reduced solution; full-grid and nonlinear accuracy require their own audits |
| Integrated trade | trade.solve_reallocation_transition |
converged concerns finite equations; use run_reallocation_horizon_ladder for tested horizon accuracy |
| Heterogeneous information | expectations.build_gaussian_information; models.solve_information_nk |
Conditional Gaussian forecasts and finite NK coefficient equations under listed signals |
| Sovereign banking | sovereign.solve_sovereign_banking |
Audited three-date pure equilibria with explicit price_selection="highest" or "lowest" |
| Adaptation and sovereign risk | sovereign.solve_sovereign_adaptation |
Audited finite-horizon Bellman equations, lender prices and discrete choices |
See the detailed guides for derivatives, continuation, SMM, robust inference, HANK, trade, information, banking and adaptation.
The experimental second-order HANK benchmark
adds models.solve_hank_second_order for small one-asset models with full
bases. It has its own derivative, equation and feasibility checks; it does not
upgrade the approximation order or acceptance criteria of existing HANK APIs.
Explicit composition
An equilibrium residual can provide sensitivities and a local branch. A caller
can then define measured model moments for SMM and use the retained simulation
batch for a point-null test. The measurement definition, units and statistical
assumptions must be supplied explicitly. This small example has equilibrium
capital = 2 * technology and an additive simulation error:
import numpy as np
from puremacro.core import EquilibriumSystem, linearize_equilibrium, continue_equilibrium
from puremacro.structural import (
MomentTargets, SimulationPlan, fit_simulated_moments, simulated_moment_test,
)
system = EquilibriumSystem(lambda x, theta: x - 2*theta, ("capital",), ("technology",))
linear = linearize_equilibrium(system, [2.], [1.])
assert linear.sensitivity().valid
branch = continue_equilibrium(system, [2.], [1.], max_steps=3)
np.testing.assert_allclose(branch.states, 2*branch.parameters, atol=1e-8)
targets = MomentTargets([2.], [[.04]], ("capital",), units="level")
plan = SimulationPlan(seed=12, replications=16, periods=20)
def simulator(theta, rng, budget):
return 2*theta + rng.normal(size=budget.periods).mean()
def derivative(theta):
return linearize_equilibrium(system, 2*theta, theta).sensitivity().jacobian
fit = fit_simulated_moments(simulator, targets, [.8], plan=plan,
definition_id="capital-plus-sample-mean-v1", jac=derivative,
parameter_names=("technology",), assume_independent=True, assume_smooth=True)
assert fit.success and fit.inference_valid
point_test = simulated_moment_test(targets, fit.simulation, assume_independent=True)
assert point_test.valid and point_test.accepted
The test at the fitted value is a descriptive compatibility check here. It is not an overidentification test or a post-selection confidence statement. For inference at a hypothesized parameter, simulate at that parameter and use its covariance. Simulation plans retain every replication, including failures. Generic callback exceptions propagate; invalid numerical moments remain unresolved rather than becoming rejection or optimization penalties.
No automatic composition joins the trade, banking, adaptation or information economies. Their household, financing, timing and terminal conditions differ. Connecting their outputs requires an explicit new economic closure. The second-order HANK API is limited to the full-basis one-asset cases described in its guide; broader HANK and other deferred model extensions remain outside these supported contracts.
Ownership, controls and saved results
Equilibrium, SMM/robust-inference, trade, Gaussian/NK and sovereign result
snapshots have detached, immutable numeric storage. Obtain a writable working
array with .copy(). Existing HANK policy classes retain their own documented
result contract. Nested diagnostic mappings and sequences
are also frozen, and report tables are detached from retained numerical data.
Legacy metadata may contain arbitrary Python objects; their internal mutability
is outside the numeric-storage contract. Equilibrium tolerances and the scalar
primitives of the trade, NK and sovereign modules accept finite real scalars,
including zero-dimensional numeric NumPy arrays. Strings, booleans, complex
values and arrays with axes are rejected. The equilibrium transpose switch
requires a boolean; continuation direction requires integer -1 or 1.
Diagnostic mappings can be exported with an explicit JSON conversion:
from collections.abc import Mapping
import json
def json_value(value):
if isinstance(value, Mapping):
return dict(value)
if isinstance(value, np.ndarray):
return value.tolist()
if isinstance(value, np.generic):
return value.item()
raise TypeError(type(value).__name__)
encoded = json.dumps(dict(fit.diagnostics), default=json_value)
assert json.loads(encoded)["assume_independent"] is True
Result dataclasses are also used to reconstruct saved arrays. Construction
alone does not rerun an economic audit. Call the corresponding audit_*
function after restoring results and inspect accepted. Malformed retained
trade/information structures return a rejected audit with a reason; a wrong
top-level argument or invalid tolerance is an input error. Audit mappings are
fresh reports, so editing a returned audit cannot change a solution.
Model fingerprint values identify specifications, not solver output or source
code. Equilibrium snapshot_id values hash the retained point, matrices and
scales. Record source hashes, package/environment versions and output hashes
separately. Example CSV/NPZ/JSON bundles illustrate persistence; they are not a
versioned universal checkpoint format. A valid audit does not establish grid
convergence, empirical calibration, infinite-horizon accuracy or release readiness.