Skip to main content

Fair, reproducible macro forecasting benchmarking package

Project description

macroforecast

Fair, reproducible macro forecasting benchmarking. One YAML recipe → end-to-end study with bit-exact replication.

ci-core ci-docs ci-typecheck python docs

v0.9.0 — extensive test suite (counts vary by extras and Python version; see CI badges above).

Renamed from macrocast -> macroforecast in v0.6.0 (PyPI namespace ownership). See CHANGELOG.md for the migration diff.

Install

pip install macroforecast                    # core
pip install 'macroforecast[deep]'            # + torch / captum (LSTM / GRU / Transformer)
pip install 'macroforecast[xgboost,lightgbm]'  # + optional gradient-boosting backends
pip install 'macroforecast[tuning]'          # + optuna for bayesian_optimization
pip install 'macroforecast[shap]'            # + shap package for richer L7 figures

Or pin to a tagged release directly from GitHub:

pip install "git+https://github.com/NanyeonK/macroforecast.git@v0.9.0"

For development:

git clone https://github.com/NanyeonK/macroforecast.git
cd macroforecast
pip install -e ".[dev]"
pip install -e ".[typecheck]"  # optional: local mypy baseline

Quick standalone use

Use individual operations directly as Python callables — no YAML needed:

import macroforecast as mf
import numpy as np

rng = np.random.RandomState(42)
X = rng.randn(100, 5)
y = X @ np.array([1, 2, 3, 4, 5]) + 0.5 * rng.randn(100)

# L4: fit a ridge model
result = mf.functions.ridge_fit(X, y, alpha=1.0)
print(result.summary())
print(result.coef_)

# L5: compute a metric
u1 = mf.functions.theil_u1(y, result.predict(X))
print(f"Theil U1 = {u1:.4f}")

# L7: permutation importance (planned for post-Cycle-22 expansion)
# imp = mf.functions.permutation_importance(result, X, y, n_repeats=30, random_state=42)
# print(imp.importances_mean)

Or use the recipe DSL for full reproducible studies — see docs/index.md and docs/two_entry_points.md for a decision guide.

5-line quickstart

import macroforecast

result = macroforecast.run("recipe.yaml", output_directory="out/")
print(result.cells[0].sink_hashes)            # per-cell sink hashes
replication = macroforecast.replicate("out/manifest.json")
assert replication.sink_hashes_match           # bit-exact replication

A minimal recipe:

0_meta:
  fixed_axes: {failure_policy: fail_fast, reproducibility_mode: seeded_reproducible}
1_data:
  fixed_axes: {custom_source_policy: custom_panel_only, frequency: monthly, horizon_set: custom_list}
  leaf_config:
    target: y
    target_horizons: [1]
    custom_panel_inline:
      date: [2018-01-01, 2018-02-01, 2018-03-01, 2018-04-01, 2018-05-01, 2018-06-01]
      y: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
      x1: [0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
2_preprocessing:
  fixed_axes: {transform_policy: no_transform, outlier_policy: none, imputation_policy: none_propagate, frame_edge_policy: keep_unbalanced}
3_feature_engineering:
  nodes:
    - {id: src_X, type: source, selector: {layer_ref: l2, sink_name: l2_clean_panel_v1, subset: {role: predictors}}}
    - {id: src_y, type: source, selector: {layer_ref: l2, sink_name: l2_clean_panel_v1, subset: {role: target}}}
    - {id: lag_x, type: step, op: lag, params: {n_lag: 1}, inputs: [src_X]}
    - {id: y_h, type: step, op: target_construction, params: {mode: point_forecast, method: direct, horizon: 1}, inputs: [src_y]}
  sinks: {l3_features_v1: {X_final: lag_x, y_final: y_h}, l3_metadata_v1: auto}
4_forecasting_model:
  nodes:
    - {id: src_X, type: source, selector: {layer_ref: l3, sink_name: l3_features_v1, subset: {component: X_final}}}
    - {id: src_y, type: source, selector: {layer_ref: l3, sink_name: l3_features_v1, subset: {component: y_final}}}
    - id: fit
      type: step
      op: fit_model
      params: {family: ridge, alpha: 0.1, min_train_size: 4, forecast_strategy: direct, training_start_rule: expanding, refit_policy: every_origin, search_algorithm: none}
      inputs: [src_X, src_y]
    - {id: predict, type: step, op: predict, inputs: [fit, src_X]}
  sinks: {l4_forecasts_v1: predict, l4_model_artifacts_v1: fit, l4_training_metadata_v1: auto}
5_evaluation:
  fixed_axes: {primary_metric: mse}

Bring your own data or model

To run a study on your own CSV / Parquet data (monthly or quarterly):

To register a custom forecasting model, preprocessor, or target transformer:

Architecture (12 layers)

L0 study setup → L1 data → L2 preprocess → L3 features (DAG, 37 ops)
                ↓                                ↓
                L1.5 / L2.5 / L3.5 (diagnostics, default-off)
                                                 ↓
              L4 model (40+ families) → L4.5 → L5 evaluation → L6 tests
                                                                    ↓
                                                  L7 interpretation → L8 output

See plans/design/part1-4 for the canonical design tables.

Operational coverage

Before relying on advanced families/tests in a paper workflow, check docs/getting_started/runtime_support.md for the exact current path coverage. Some listed families are wired through legacy/specialized paths or optional extras, not necessarily through the minimal core runtime end-to-end.

  • 40+ L4 families — linear (8), tree / boosting (8), SVM (3), kNN, MLP, deep NN (3, opt-in via [deep]), AR_p, factor_augmented_ar, BVAR Minnesota / NIW, FAVAR, MRF GTVP (Coulombe 2024), DFM (Mariano-Murasawa MQ Kalman), quantile_regression_forest, bagging.
  • 18 L7 figure types — bar / heatmap / pdp / ALE / SHAP family / attribution / IRF with CI / decomp stacked / state choropleth.
  • L6 tests — Diebold-Mariano (with HLN + HAC kernels), Clark-West, Giacomini-Rossi (simulated CVs), MCS / SPA / RC / StepM via stationary bootstrap, Pesaran-Timmermann, residual battery, density tests (PIT-Berkowitz / KS / Kupiec / Christoffersen / Engle-Manganelli DQ), Diebold-Mariano-Pesaran joint multi-horizon.
  • L1.G regimes — none / NBER / user-provided / Hamilton MS / Tong SETAR / Bai-Perron breaks.
  • 3 sweep kinds — param-level ({sweep: [...]}), recipe-level (external axis), node-level (sweep_groups). Combine via grid (default) or zip.
  • Sub-cell parallelismparallel_unit ∈ {cells, models, oos_dates, horizons, targets}.
  • Bit-exact replicationreplicate() re-executes and verifies per-cell sink hashes match.

Recipe gallery

examples/recipes/ ships 38 bundled reference recipes; new in v0.3:

  • l4_minimal_ridge.yaml — minimal ridge on a custom panel.
  • l4_random_forest.yaml, l4_xgboost.yaml, l4_lightgbm.yaml (when extras installed).
  • l4_quantile_regression_forest.yaml — Meinshausen QRF with quantile bands.
  • l4_bagging.yaml — bootstrap-aggregated ridge.
  • l4_dfm_mariano_murasawa.yaml — mixed-frequency DFM.
  • l4_macroeconomic_random_forest.yaml — Coulombe MRF GTVP.
  • l4_ensemble_ridge_xgb_vs_ar1.yaml — horse race with benchmark.

A replication script for Coulombe (2024) MRF on FRED-MD lives at examples/replication/coulombe_2024_mrf_fred_md.py.

Browse the full encyclopedia (every layer × sublayer × axis × option, with OptionDoc summaries / when-to-use / references) at docs/encyclopedia/.

Status levels

Two-value vocabulary (defined in macroforecast.core.status):

  • operational — runtime executes the full design-spec procedure.
  • future — schema-only; validator hard-rejects, runtime raises NotImplementedError.

The package shipped 19 honesty-pass demotions in v0.1.1; all of them have real implementations in v0.2 / v0.25 / v0.3 (every future flag in the v0.1.1 audit table is now operational).

Citing

If you use macroforecast in published work, please cite:

macroforecast: Fair, reproducible macro forecasting benchmarking. v0.6.0, 2026.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

macroforecast-0.9.2b1.tar.gz (652.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

macroforecast-0.9.2b1-py3-none-any.whl (716.3 kB view details)

Uploaded Python 3

File details

Details for the file macroforecast-0.9.2b1.tar.gz.

File metadata

  • Download URL: macroforecast-0.9.2b1.tar.gz
  • Upload date:
  • Size: 652.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for macroforecast-0.9.2b1.tar.gz
Algorithm Hash digest
SHA256 ae8f464e55c4e0ab321b7a390bce4f2167fa84221ac128d97897dc17d87db4e3
MD5 365acf15ea709c18eb423b6299165182
BLAKE2b-256 4469c9e031bab3910ba25bde7f8daf380f367372e00b51bf3e7580004aee3fb3

See more details on using hashes here.

File details

Details for the file macroforecast-0.9.2b1-py3-none-any.whl.

File metadata

  • Download URL: macroforecast-0.9.2b1-py3-none-any.whl
  • Upload date:
  • Size: 716.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for macroforecast-0.9.2b1-py3-none-any.whl
Algorithm Hash digest
SHA256 933b0f2447b910aac93502e6f773a1e29efa9aa7bc34cd48e9f38a4b8152f5c5
MD5 fb7454eac23f99fa970174c63f17c537
BLAKE2b-256 e5d49cbd444589da2be086acdd9f4003bef300750babd1d5571aaa95d32bc4f3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page