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.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:
:doc:`rescreen ` (second-pass Morris screening with locked parameters),
:doc:`cost ` (budget-aware cost classification),
:doc:`cross-eval ` (cross-scenario ranking with harmonic/geometric/min strategies),
and :doc:`sweep ` (multi-stage parameter sweep with carry-forward winners).
Changed
~~~~~~~
**Validation Targets**
* All three scenarios recalibrated from pixel-level extraction of book figures
(see :doc:`/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 :ref:`decision-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 :ref:`decision-batch-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**
* :class:`~bamengine.Extension` dataclass: bundles roles, events, relationships,
and config into a single object.
* :meth:`~bamengine.Simulation.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``: ``loyalty`` → ``random``.
* **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.py`` →
``events/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 × ratio`` → ``prod × 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_ceiling`` → ``unemployment_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**: ``destroyed`` → ``collapsed`` 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``/``metrics`` → ``validation.types``/``scoring``/``engine``
* ``CalcAnnualInflationRate`` → ``CalcInflationRate`` (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_wage`` → ``min_wage_ratio``
* ``net_worth_init`` → ``net_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 ``FirmsCalcCreditMetrics`` → ``FirmsCalcFinancialFragility`` 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.*