Release History#

All notable changes to BAM Engine are documented here.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Note

Pre-1.0 releases (0.x.x) may introduce breaking changes between minor versions.

[0.10.2] - 2026-07-09#

This patch makes memory scale near-linearly at large populations. The credit market previously built a dense (borrowers x lenders) scratch matrix to sample each firm’s candidate banks; because the number of banks grows with the number of firms, that allocation was O(n_firms^2) and dominated peak memory at scale. Replacing it with the existing sparse sampler cuts peak RSS at 20,000 firms from about 553 MB to about 211 MB and removes the super-linear knee, while leaving steady-state runtime and the model’s statistical behaviour unchanged.

Changed#

Performance

  • Credit-market loan-application sampling no longer materialises a dense (borrowers x lenders) random-score matrix (O(n_firms^2) because the number of lenders scales with the number of firms). It now uses the same O(borrowers x H) sparse without-replacement draw already used by the labor and goods markets. Peak RSS at 20,000 firms drops from about 553 MB to about 211 MB and memory scaling becomes near-linear; steady-state runtime is unchanged.

[0.10.1] - 2026-07-07#

This patch prepares the JOSS submission: it fixes the [comparison] extra, adds the JOSS paper sources with a CI-built draft PDF, and adds reviewer-facing reproduction instructions for the cross-framework benchmark.

Fixed#

  • pip install bamengine[comparison] no longer pulls mesa-frames into the main environment (its numpy<2 pin conflicted with the modern NumPy the benchmark measures; the mesa-frames runner uses its own dedicated venv), and now includes networkx, which Mesa 3.5 imports at package-import time but does not declare (previously the Mesa benchmark runner failed silently on fresh clones).

  • The mesa-frames equivalence-gate test now skips (like its sibling tests) when the optional dedicated venv is absent, instead of failing.

Added#

  • JOSS paper sources under paper/ and a draft-pdf.yml workflow that compiles the paper on every change.

  • “Reproducing the benchmark” quickstart in comparison/README.md and a cross-framework benchmark section in the README.

[0.10.0] - 2026-07-06#

This release makes BAM Engine measurable against the wider agent-based modelling ecosystem. A new cross-framework benchmark suite runs the identical baseline BAM model on five frameworks (BAM Engine, Mesa, mesa-frames, Agents.jl, and NetLogo) and confirms behavioural equivalence before comparing runtime and memory. To back that comparison, the core simulation gained a round of vectorization work and an optional Numba kernel that together make BAM Engine the fastest of the group at scale. No breaking changes to the public API.

Added#

Goods-Market Numba Kernel

  • Optional Numba JIT kernel for the goods market (pip install bamengine[fast]): bit-identical results, approximately 2x speedup at scale, opt-in via the new goods_kernel config parameter ("auto" / "numba" / "python").

Cross-Framework Benchmark Suite

  • New comparison/ harness that runs the baseline BAM model across five frameworks and compares runtime and peak memory on a common size matrix. Each port passes a behavioural-equivalence gate (20 seeds) against BAM Engine before its timings are reported.

  • Ports added: an idiomatic OOP Mesa port, a Polars-backed mesa-frames port, an Agents.jl (Julia) port, and a NetLogo cross-language reference runner via a pyNetLogo bridge.

  • Orchestrator, subprocess runner with peak-RSS sampling, central equivalence metric, and an aggregate analysis/plot/report pipeline.

Changed#

Performance

  • Sparse O(N*k) market matching via a new sample_k_per_row sampler, replacing the dense priority-matrix approach: roughly 8.8x faster at 1000 firms and scaling to 20000 firms, with validation scores preserved.

  • Goods-market sequential loop and firing pass micro-optimized (bit-identical, ~20-28% faster at scale); vestigial dense recv_job_apps / recv_loan_apps arrays removed.

  • Core hot paths switched from np.isin / np.setdiff1d to boolean masks, and the contract triple-scan merged into a single pass.

Development & CI

  • Canonical dev/test environment now exercises the Numba kernel (numpy<2.5), with an added CI fallback lane on numpy 2.5 (no Numba) so both code paths are tested. The [fast] extra moved from the test extra to the dev extra.

[0.9.2] - 2026-06-23#

This patch restores compatibility with NumPy 2.5 and bundles validation, documentation, and tooling fixes accumulated since 0.9.1.

Fixed#

  • Restored NumPy 2.5 compatibility: custom roles attached via Simulation.use_role() again get correct (non-float64) dtypes, and mypy no longer trips on NumPy 2.5’s typed stubs.

  • Validation and robustness figure fixes (baseline target bounds, collapsed-seed statistics).

Changed#

  • Simulation.use_role() now raises TypeError on an unresolvable field annotation instead of silently defaulting to float64.

Added#

  • CONTRIBUTING.md.

[0.9.1] - 2026-03-19#

This patch adds a convenience log_level parameter to Simulation.init() for simpler logging configuration.

Added#

  • log_level keyword argument on Simulation.init(): shorthand for logging={"default_level": "..."} (e.g., Simulation.init(seed=42, log_level="WARNING")).

[0.9.0] - 2026-03-19#

This release redesigns the results collection API with intuitive access patterns, automatic economy collection, and unaggregated data by default.

Added#

Results API

  • String-key access: results["Producer.production"], results["Economy.inflation"].

  • Attribute access: results.Producer.production, results.Economy.inflation.

  • results.get("Producer", "production", aggregate="mean") for on-demand aggregation, replacing the deprecated get_array() method.

  • results.available() lists all collected data fields.

  • sim.collectables() lists what data can be collected before calling run().

Changed#

Results Collection Defaults

  • sim.run() now returns results by default (collect=True).

  • collect=True and list-form collect now produce unaggregated 2D arrays with shape (n_periods, n_agents) instead of mean-aggregated 1D arrays. Use results.get(..., aggregate="mean") for the previous behavior.

  • Economy metrics (average price, inflation, etc.) are always collected automatically when collection is active.

Deprecated#

  • SimulationResults.get_array() is deprecated in favor of SimulationResults.get().

Removed#

  • Dead unemp_rate_history field from Economy (was never updated after the CalcUnemploymentRate event was removed in v0.5.0).

[0.8.0] - 2026-03-17#

This release extends the calibration toolkit with four new composable tools, recalibrates all validation targets from extracted book figure data, and redesigns buffer-stock validation around aggregate improvement over Growth+.

Added#

Calibration Tools

  • Four new composable CLI tools for multi-scenario calibration workflows: rescreen (second-pass Morris screening with locked parameters), cost (budget-aware cost classification), cross-eval (cross-scenario ranking with harmonic/geometric/min strategies), and sweep (multi-stage parameter sweep with carry-forward winners).

Changed#

Validation Targets

  • All three scenarios recalibrated from pixel-level extraction of book figures (see Validation Targets).

Buffer-Stock Validation

  • Replaced the duplicated 30-metric system with a focused two-layer approach: 8 unique buffer-stock metrics (wealth fits, Gini, MPC, dissaving) for per-seed validation, plus aggregate improvement over Growth+ assessed at stability level.

Calibrated Defaults

  • new_firm_price_markup: 1.15 → 1.20.

Fixed#

  • Division-by-zero in score_outlier_penalty when max_outlier_pct=0.

  • Collapsed buffer-stock result incorrectly reporting passed=True.

[0.7.0] - 2026-03-13#

This release replaces the v0.6.0 batch-sequential goods market with a pure sequential implementation.

Changed#

Sequential Goods Market

  • goods_market_round now processes consumers one at a time using a sequential Python-list loop, replacing the batch-sequential approach (~10 randomized consumer batches) from v0.6.0. Each consumer completes all shopping visits before the next consumer starts, eliminating many “phantom goods” overselling events per period caused by within-batch inventory collisions. See Goods Market: Sequential Shopping for design rationale.

Validation Metrics

  • price_ratio_floor (Growth+): changed from global minimum to 1st percentile, which filters transient demand surges at full employment while still catching genuine deflationary spirals; weight also lowered from 3.0 to 2.0.

Performance#

  • Sequential goods market is 6.5% faster than batch-sequential for full simulations. goods_market_round itself dropped 35%.

Removed#

  • n_batches config parameter (only needed for batch-sequential goods market).

Development#

Seed-Stability Testing Overhaul

  • Seed stability tests upgraded from 20 to 100 seeds per scenario, with parallel execution via new n_workers parameter.

  • New benchmarks/bench_seed_stability.py, a parallelized 1000-seed benchmark runner with JSON output, git-worktree support for historical commits, and CLI (--scenario, --seeds, --tags, --commits). Results committed to benchmarks/results/.

  • New .github/workflows/validation-status.yml replaces validation.yml and growth-plus-stability.yml; reads pre-computed JSON in benchmarks/results/ with zero simulation in CI.

[0.6.1] - 2026-03-10#

This patch eliminates the last Python loops in grouped random selection (resolve_conflicts, firms_fire_excess_workers, firms_fire_workers) by replacing per-group rng.choice/rng.permutation calls with a vectorized random-priority + lexsort pattern.

Performance#

  • Vectorized resolve_conflicts: replaced per-target Python loop + rng.choice with rng.random() + np.lexsort + grouped rank comparison. 3.4x faster (0.100s → 0.029s, 7.5% → 2.3% of runtime).

  • Vectorized firms_fire_excess_workers: replaced per-firm rng.permutation loop with _flatten_and_shuffle_groups helper + rank threshold.

  • Vectorized firms_fire_workers: replaced per-firm cumsum loop with _flatten_and_shuffle_groups + grouped_cumsum + np.minimum.reduceat.

  • New shared helper _flatten_and_shuffle_groups extracts items from ragged group boundaries into a flat shuffled array using random-priority lexsort.

[0.6.0] - 2026-03-09#

This release consolidates two parallel market matching implementations (sequential Python loops vs. vectorized NumPy batches) into a single vectorized implementation. Simulation behavior is preserved.

Changed#

Vectorized Market Matching

  • Labor market: labor_market_round replaces workers_send_one_round + firms_hire_workers. Batch conflict resolution via resolve_conflicts() utility. Pipeline calls it max_M times (one round per call).

  • Credit market: credit_market_round replaces firms_send_one_loan_app + banks_provide_loans. Firms sorted by projected_fragility (ascending leverage) within each target bank; grouped_cumsum() tracks per-bank supply exhaustion. Pipeline calls it max_H times.

  • Goods market: goods_market_round replaces consumers_shop_sequential. Uses batch-sequential processing (~10 randomized consumer batches, each completing all Z visits before the next starts). Pipeline calls it once (handles visits internally). See Goods Market: Sequential Shopping for design rationale.

Performance#

  • Vectorized batch matching yields ~30% faster full simulation runs across all economy sizes. See ASV benchmarks.

Removed#

  • Sequential event classes: WorkersSendOneRound, FirmsHireWorkers, FirmsSendOneLoanApp, BanksProvideLoans, ConsumersShopSequential.

  • Interleave syntax (``<->``) from pipeline YAML. Only event x N repetition remains.

[0.5.1] - 2026-03-04#

Performance#

  • Vectorized workers_decide_firms_to_apply: replaced three Python for-loops (per-worker rng.choice(), per-loyal-worker move-to-front, per-worker buffer write) with batch NumPy operations (random priorities + argpartition, vectorized loyalty shift, slice assignment). ~3.5x faster event execution.

[0.5.0] - 2026-03-04#

Added#

Extension Bundles

  • Extension dataclass: bundles roles, events, relationships, and config into a single object.

  • use(): one-call extension activation (replaces the manual use_role/use_events/use_config pattern).

  • Pre-built bundles: RND, BUFFER_STOCK, TAXATION in their respective extensions.* packages.

  • Collect-config dicts: BASELINE_COLLECT, RND_COLLECT, BUFFER_STOCK_COLLECT, suggested data-collection configs for sim.run(collect=...).

Documentation

  • Extended User Guide to guide user through simulations, configuration, custom data collection, custom roles/events/relationships, pipelines, operations, extensions, validation, calibration, and best practices.

  • New pages: Related Projects, Roadmap, Glossary, About.

Removed#

  • Deprecated config parameters: price_cut_allow_increase, inflation_method, labor_matching, credit_matching, min_wage_ratchet, pricing_phase, matching_method. Behavior is now hardcoded to the previously active defaults.

  • Deprecated event classes: WorkersApplyToFirms, WorkersApplyToBestFirm, FirmsApplyForLoans, CalcUnemploymentRate, ConsumersShopOneRound, FirmsCalcBreakevenPrice, FirmsAdjustPrice.

  • Deprecated internal functions: cascade matching (labor and credit), simultaneous matching, annualized inflation, ratchet minimum wage, production-phase pricing, round-robin shopping.

Fixed#

  • Calibration modules now fall back to serial execution when n_workers=1, fixing a ProcessPoolExecutor spawn crash on macOS.

[0.4.0] - 2026-02-25#

This release adds the robustness analysis package (Section 3.10 of Delli Gatti et al., 2011), overhauls the calibration package, re-calibrates defaults, and fixes several issues in internal event logic.

Added#

Robustness Analysis

  • validation/robustness/ package implementing Sections 3.10.1–3.10.2:

    • Exploration of the parameter space (Section 3.10.1)

      • Internal validity: 20-seed stability of co-movements, AR structure, firm size distributions, and empirical curves (HP filter, cross-correlations, AR fitting, impulse-response).

      • Sensitivity analysis: univariate sweeps across credit (H), goods (Z), labor (M), contract length (theta), and economy size.

    • Preferential attachment in consumption and the entry mechanism (Section 3.10.2)

      • Preferential attachment: New experiment (run_pa_experiment) that removes PA by setting new config parameter consumer_matching: loyaltyrandom.

      • Entry mechanism: New experiment (run_entry_experiment) that uses the new taxation extension (extensions/taxation/).

    • CLI: python -m validation.robustness --help

    • Example: examples/extensions/example_robustness.py

Packaging

  • extensions/, validation/, calibration/ are now pip-installable sibling packages (pip install bamengine[validation], etc.).

Fixed#

  • New FirmsPlanBreakevenPrice / FirmsPlanPrice events (mutually exclusive with production-phase pair). Source relocation: events/planning.pyevents/production.py (pipeline keys unchanged).

  • Loan records retained through planning/labor phases (purged at credit market opening) for previous-period interest access.

  • projected_fragility pre-filled with max_leverage for NW ≤ 0 firms.

  • Loan rate now uses per-bank opex_shock (φ_k) instead of constant h_phi upper bound, restoring bank heterogeneity (book eq. 3.7).

  • Multi-lender: firms accumulate loans from multiple banks across credit rounds.

  • LoanBook.principal_per_borrower() new method for efficient per-firm principal aggregation.

  • Removed spurious wage_bill recalculation in workers_update_contracts (overstated gross profit).

  • Bad debt: clip(frac × NW, 0, principal) computes recovery, was subtracted as loss. Now loss = principal - recovery.

  • R&D deduction moved before dividends (book Section 3.8); operates on net_profit so dividends = δ(1−σ)π.

  • net_worth_ratio formula: prod × ratioprod × price × ratio (dimensional fix).

  • Bankruptcy counters persist through end-of-period data capture.

  • Spawned firms set production = production_prev (prevents re-bankruptcy).

Changed#

Validation

  • Unemployment metrics restructured: unemployment_pct_in_bounds → separate floor/ceiling checks; unemployment_hard_ceilingunemployment_absolute_ceiling (30% → 20%, BOOLEAN in baseline). Removed unemployment_autocorrelation.

Calibration

  • Rebuilt into focused modules (analysis, grid, screening, stability, io, reporting), replacing monolithic optimizer.py.

  • Morris Method screening (default): multi-trajectory OAT (Morris 1991) with dual-threshold classification (mu* and sigma). OAT via --method oat.

  • Tiered stability: incremental tournament (100×10 → 50×20 → 10×100 seeds).

  • Pairwise interaction analysis for synergy/conflict detection.

  • Phase-based CLI (--phase, --resume, --rank-by, --grid, --fixed), markdown reports, config export, before/after comparison.

Breaking Changes

  • Calibrated defaults: n_firms 300→100, n_households 3000→500, New-firm entry: size 0.8→0.5, production 0.9→0.5, wage 0.9→0.5, markup 1.0→1.5, job_search_method: "vacancies_only""all_firms", matching_method: "simultaneous""sequential" (also removed from config)

  • Config removed: contract_poisson_mean, loan_priority_method, firing_method, matching_method

  • Config deprecated: price_cut_allow_increase, inflation_method

  • Net worth: net_worth_ratio semantics → “multiple of initial revenue”; default 3.0 → 6.0

  • Renamed: destroyedcollapsed on Simulation

  • Calibration CLI: --phase replaces --sensitivity-only; new --resume, --rank-by, --k-factor, --output-dir

[0.3.0] - 2026-02-11#

This release adds the buffer-stock consumption extension (Section 3.9.4 of Delli Gatti et al., 2011), completing all three BAM scenarios from the book, and introduces a composable extension API (use_events, use_config, use_role with n_agents) that replaces the global hook registry.

Added#

Consumption & Buffer-stock Extension

  • Consumption & buffer-stock extension (Chapter 3.9.4 of Delli Gatti et al., 2011):

    • extensions/buffer_stock/ package with BufferStock role and replacement events

    • Individual adaptive MPC based on buffer-stock saving theory (Eq. 3.20)

    • Validation scenario with ~30 metrics: wealth CCDF fitting (Singh-Maddala, Dagum, GB2), Gini coefficient, MPC distribution, baseline macro dynamics

    • 8-panel visualization with CCDF plot (Figure 3.8 replica)

    • Example: examples/extensions/example_buffer_stock.py

  • Shareholder role: built-in household role tracking per-period dividends, used to adjust buffer-stock MPC metrics for the dividend artifact

Composable Extension API

  • Simulation.use_config(config): apply extension default configuration with “don’t overwrite” semantics (user kwargs and earlier use_config() calls take precedence)

  • Simulation.use_events(*event_classes): explicitly apply pipeline hooks from event classes

  • Simulation.use_role(cls, n_agents=N): n_agents parameter for non-firm roles

  • Pipeline.apply_hooks(*event_classes): read hook metadata from classes and apply to pipeline

Changed#

Breaking

  • @event(after=..., before=..., replace=...) now stores hook metadata as class attributes instead of writing to a global dict. Hooks are applied explicitly via sim.use_events(). Removed _EVENT_HOOKS global dict, register_event_hook(), get_event_hooks(), and the apply_hooks parameter from Pipeline.from_yaml() / Pipeline.from_event_list().

  • Default aggregate for dict-form collect changed from "mean" to None. Callers using collect={...} without an "aggregate" key now get full per-agent data. Add "aggregate": "mean" explicitly for the previous behavior. collect=True and list-form collect are unchanged (still aggregate with mean).

Scenario Validation

  • Weight-based fail escalation for validation status checks: high-weight metrics fail more easily, low-weight metrics are more lenient. New escalation parameter on status check functions. This also resolves the growth+ seed stability test failures in v0.2.2 by widening the WARN zone for lower-weight metrics.

  • Validation scenarios restructured into self-contained directory packages (validation/scenarios/{baseline,growth_plus,buffer_stock}/), each co-locating code, visualization, targets, and output. Scenario.targets_file renamed to Scenario.targets_path: Path; new SCENARIO_REGISTRY dict and get_scenario() lookup function.

  • Widened some validation targets to reduce false negatives from seed sensitivity

[0.2.2] - 2026-02-09#

This release completes the Growth+ scenario (Section 3.9.2 of Delli Gatti et al., 2011), bringing its validation metrics, financial dynamics analysis, and visualizations in line with the book, and re-calibrates model defaults accordingly.

Added#

  • Growth+ financial dynamics metrics: Minsky classification, recession detection, GDP cyclicality correlations, Laplace tent-shape R², CV-based dispersion checks

  • max_leverage and inflation_method configuration parameters

  • Relationship data collection in SimulationResults; new n_firm_bankruptcies, n_bank_bankruptcies economy metrics

  • extensions/rnd/ standalone package (R&D extension extracted from validation)

Changed#

Breaking

  • Re-calibrated defaults: new_firm_size_factor 0.9→0.8, max_loan_to_net_worth 100→2, max_leverage uncapped→10, matching_method “sequential”→”simultaneous”; removed cap_factor and fragility_cap_method

  • Restructured validation package: validation.core/runners/metricsvalidation.types/scoring/engine

  • CalcAnnualInflationRateCalcInflationRate (pipeline key: calc_inflation_rate)

  • R&D import path: from extensions.rnd import RnD (was in validation package)

Events Pipeline

  • firms_calc_breakeven_price and firms_adjust_price events moved to production phase (before firms_run_production)

Known Issues#

  • Growth+ seed stability test failures are a calibration issue and will be addressed in a future release. The baseline scenario passes the stability test at 100%.

[0.2.1] - 2026-01-21#

This patch release simplifies examples and reorganizes the validation package for better maintainability.

Changed#

Validation Package

  • Restructured validation package into subpackages:

    • validation/metrics/ - metric computation from simulation results (baseline.py, growth_plus.py)

    • validation/scenarios/ - detailed visualizations with target bounds

    • validation/targets/ - YAML target definitions (unchanged)

  • Moved RnD role and events to validation/scenarios/growth_plus_extension.py

Examples Simplification

  • Simplified example_baseline_scenario.py and example_growth_plus.py to be self-contained

  • Examples focus on teaching core BAM Engine concepts; users are directed to validation package for detailed analysis with bounds

Fixed#

  • Fixed Sphinx Gallery compatibility by handling missing __file__ in exec() environment

[0.2.0] - 2026-01-20#

This is a major release introducing validation and calibration frameworks, significant performance improvements, and API enhancements for model extensibility.

Added#

Validation Package (validation/)

  • Complete acceptance testing framework against empirical targets from Delli Gatti et al. (2011)

  • Two validation scenarios: Baseline (Section 3.9.1) and Growth+ (Section 3.8)

  • Core API: run_validation(), run_stability_test(), run_growth_plus_validation()

  • Scoring system with ValidationScore, StabilityResult, MetricResult types

  • YAML target definitions (validation/targets/) with inline documentation

  • Multi-seed stability testing for calibration workflows

  • Reporting functions: print_validation_report(), print_stability_report()

Calibration Package (calibration/)

  • Parameter optimization framework with four-phase calibration process:

    1. One-at-a-time (OAT) sensitivity analysis to identify impactful parameters

    2. Focused grid building with HIGH/MEDIUM/LOW sensitivity categorization

    3. Grid search screening using single seed

    4. Multi-seed stability testing for top candidates

  • CLI interface: python -m calibration --scenario baseline --workers 10

  • Programmatic API: run_sensitivity_analysis(), build_focused_grid(), run_focused_calibration()

  • Parallel execution with ProcessPoolExecutor for speed

  • Supports both baseline and growth_plus scenarios

Event Pipeline Hooks

  • New @event decorator parameters for automatic pipeline positioning:

    • after="event_name" - insert after specified event

    • before="event_name" - insert before specified event

    • replace="event_name" - replace specified event

  • Enables clean model extensions without manual insert_after() calls

  • Example usage:

    @event(after="firms_pay_dividends")
    class MyCustomEvent:
        def execute(self, sim):
            ...  # Automatically positioned in pipeline
    

Data Collection Enhancements

  • Timed capture system: capture data after specific events via capture_after="event_name"

  • Pipeline callback registration: pipeline.register_after_event(event_name, callback)

  • New SimulationResults.get_array() method for convenient data access:

    results.get_array("Producer", "price", aggregate="mean")
    
  • New SimulationResults.data property for unified role + economy access

  • Support for Economy as pseudo-role in data access

Configuration Parameters

  • New ratio-based initialization parameters:

    • min_wage_ratio - minimum wage relative to mean wage

    • net_worth_ratio - net worth relative to production level

    • labor_productivity - goods produced per worker

  • New firm entry parameters: new_firm_size_factor, new_firm_production_factor, new_firm_wage_factor, new_firm_price_markup

  • New implementation variant parameters:

    • loan_priority_method - bank ranking: “by_leverage” | “by_net_worth” | “by_appearance”

    • firing_method - worker selection: “random” | “expensive”

    • matching_method - labor market: “sequential” | “simultaneous”

    • job_search_method - sampling: “vacancies_only” | “all_firms”

  • New credit constraint parameters: max_loan_to_net_worth, max_leverage

Operations Module

  • ops.exp() - exponential function for growth models

  • ops.array() - create array copies (vs asarray() which doesn’t copy)

Benchmarking

  • Seven comprehensive ASV benchmark suites: SimulationSuite, PipelineSuite, MemorySuite, CriticalEventSuite, InitSuite, LoanBookSuite, ScalingSuite

  • Quick pytest-benchmark suite for fast local feedback

  • Baseline comparison functionality for performance regression detection

CI/CD

  • Dedicated validation workflow (.github/workflows/validation.yml)

  • New pytest marker @pytest.mark.validation for acceptance tests

Examples

  • Growth+ extension example (850+ lines) demonstrating R&D-driven productivity growth, pipeline hooks, and extension parameters

  • Enhanced baseline example (600+ lines) with full validation integration and 8-panel visualization

Changed#

Breaking: Configuration System

  • Replaced absolute initialization values with ratio-based parameters:

    • min_wagemin_wage_ratio

    • net_worth_initnet_worth_ratio

    • production_init removed (calculated from labor_productivity)

    • wage_offer_init removed (calculated from balance sheets)

  • Default agent counts changed: n_firms: 100 → 300, n_households: 500 → 3000

  • Default dividend rate changed: delta: 0.40 → 0.10

  • Default bank capital ratio changed: v: 0.06 → 0.10

Breaking: Results API

  • results.economy renamed to results.economy_data

  • Data collection now requires explicit collect=True parameter in run()

Event System

  • Renamed FirmsCalcCreditMetricsFirmsCalcFinancialFragility for clarity

  • Reordered price events: breakeven calculation → price adjustment → production → average price update

Performance

  • Optimized logging with per-event enabled/disabled flags (~75-80% faster event execution)

  • Vectorized firm selection in labor and goods markets

  • Optimized hot loops in goods and labor market events

  • Overall throughput improved 50-80% compared to v0.1.2

    • Small (100 firms): ~500 periods/s

    • Medium (200 firms): ~240 periods/s

    • Large (500 firms): ~77 periods/s

Testing

  • Achieved ~100% test coverage with targeted tests and pragma markers

  • Added comprehensive tests for edge cases, error paths, and event hooks

Documentation

  • New validation/README.md and calibration/README.md package documentation

  • Expanded docs/development.rst with validation and calibration workflows

  • Updated docs/user_guide/data_collection.rst with timed capture examples

  • Updated docs/user_guide/pipelines.rst with pipeline hooks documentation

Dependencies

  • Added scipy>=1.11 for validation metrics (skewness, percentiles)

  • Added pandas-stubs>=2.0 for mypy type checking

Fixed#

Labor Market

  • Fixed worker wages not updating when minimum wage increases

  • Fixed excess labor firing event placement in pipeline

  • Fixed labor market worker shuffling for proper sequential matching

Goods Market

  • Fixed loyalty and preferential attachment behavior in consumer firm selection

  • Fixed price event ordering to use projected output for breakeven price calculation

  • Fixed average market price update to account for current period’s actual production

Core

  • Fixed bank equity test for total market collapse scenarios

[0.1.2] - 2025-12-05#

Added#

  • Documentation: New section for API reference, Examples, Performance & Profiling, available on Read the Docs

  • Examples: Basic and advanced examples using Sphinx Gallery format

  • Benchmarking: ASV benchmarking workflow with GitHub Pages deployment

  • CI/CD: sp-repo-review compliance for Scientific Python standards

  • CI/CD: pre-commit.ci and Dependabot integration

Changed#

  • Replaced black formatter with ruff-format

  • Refactored all examples to use bam.ops instead of raw NumPy operations

  • Improved docstrings throughout codebase for Sphinx compatibility

[0.1.1] - 2024-11-14#

Added#

  • CI/CD: GitHub Actions workflows for automated testing and PyPI publishing

    • Cross-platform testing on Ubuntu, macOS, and Windows

    • Multi-version testing for Python 3.11, 3.12, 3.13

    • Automated PyPI publishing on GitHub releases

Changed#

  • Breaking: Dropped Python 3.10 support. Minimum required Python version is now 3.11+

    • Python 3.10 had complex metaclass compatibility issues in decorators that are not worth maintaining

    • Supported versions: Python 3.11, 3.12, 3.13

Fixed#

  • Windows compatibility in test suite (file handle management, path separators)

[0.1.0] - 2025-11-13#

This release is feature-complete for the core BAM model but APIs may change in future releases. Designed for academic research and policy analysis experiments.

Added#

Core ECS Architecture

  • Role (Component): Dataclasses with NumPy arrays for agent state, auto-registration via __init_subclass__

  • Event (System): Pure functions wrapped in Event classes, YAML-configurable pipeline execution

  • Relationship: Many-to-many connections with COO sparse format (e.g., LoanBook for loans)

  • Registry: Global auto-registration for roles, events, and relationships

  • Pipeline: YAML-based event ordering with special syntax (repeat, interleave, parameter substitution)

  • Simulation engine: Simulation class managing agents, roles, relationships, and event execution

User-Facing API

  • Simplified definitions: @role, @event, @relationship decorators for easy creation of components

  • Type aliases: Float, Int, Bool, AgentId for bam-engine type hints

  • Operations module: 30+ operations (ops.add, ops.divide, etc.) that wrap NumPy operations with safe handling

  • Read methods: sim.get_role(), sim.get_event(), sim.get_relationship() with case-insensitive lookup

BAM Model Implementation

  • 3 agent populations: Firms, Households, Banks

  • 6 agent roles: Producer, Employer, Borrower, Worker, Consumer, Lender

  • 8 event modules: Planning, labor/credit/goods markets, production, revenue, bankruptcy, economy stats (43 total events)

Configuration & Validation

  • Three-tier configuration: Package defaults → User YAML → Keyword arguments

  • Centralized validation: Type checking, range validation, relationship constraints

  • Custom pipeline support: Load custom event sequences via pipeline_path parameter

  • Logging configuration: Global and per-event log levels (DEBUG, INFO, WARNING, ERROR, TRACE)

Performance & Testing

  • Vectorized Operations: NumPy-based computations for efficient large-scale simulations

  • Sparse Relationships: COO sparse matrix format for memory-efficient relationship storage

  • Benchmarking: 172 periods/s (small), 96 periods/s (medium), 40 periods/s (large) - 4-9x faster than targets

  • Testing: Unit tests, integration tests, property-based tests, performance regression tests, covering >99% of codebase

  • Deterministic RNG: Reproducible simulations with seed control


See the GitHub Releases for complete release history.