Model Extensions#
BAM Engine includes three built-in extensions that add economic mechanisms beyond the baseline BAM model. Extensions follow a consistent pattern: define new roles and events, package them with a config dictionary, and activate them explicitly after simulation initialization.
The Extension Pattern#
Every extension provides a pre-built Extension bundle that
activates all components in a single call:
import bamengine as bam
from extensions.rnd import RND
sim = bam.Simulation.init(seed=42)
sim.use(RND) # registers role, events, and config
For finer control, each extension also exports individual components (a role
class, an event list (*_EVENTS), and a config dictionary (*_CONFIG))
that can be activated manually:
from extensions.rnd import RnD, RND_EVENTS, RND_CONFIG
sim = bam.Simulation.init(seed=42)
sim.use_role(RnD)
sim.use_events(*RND_EVENTS)
sim.use_config(RND_CONFIG)
Warning
When using the manual pattern, all three steps are required. Forgetting
use_events() means the extension events will never execute. Forgetting
use_config() means extension parameters will be missing at runtime.
Using sim.use() avoids this problem.
Built-in Extensions#
BAM Engine ships with three extensions:
Growth+ (R&D): Endogenous productivity growth via R&D investment (Section 3.8). Firms invest profits in R&D, producing stochastic productivity gains.
Buffer-Stock Consumption: Target savings-to-income ratio mechanism (Section 3.9.4). Households adjust spending based on a savings buffer target.
Taxation: Profit taxation without redistribution (Section 3.10.2). Designed for structural experiments on entry dynamics.
See also
Full reference for each extension, including role fields, events, configuration parameters, and autodoc API:
Growth+ (R&D) Extension: Growth+ (R&D)
Buffer-Stock Consumption Extension: Buffer-Stock Consumption
Taxation Extension: Taxation
Combining Extensions#
Multiple extensions can be used together. Apply them in order, with R&D events before taxation (since R&D deducts from net profit before tax):
import bamengine as bam
from extensions.rnd import RND
from extensions.buffer_stock import BUFFER_STOCK
from extensions.taxation import TAXATION
sim = bam.Simulation.init(seed=42)
sim.use(RND)
sim.use(BUFFER_STOCK)
sim.use(TAXATION)
results = sim.run(n_periods=1000, collect=True)
Writing Your Own Extension#
Follow the same pattern as the built-in extensions:
Define a role (if new state variables are needed):
from bamengine import role from bamengine.typing import Float @role class MyExtension: custom_field: Float
Define events with pipeline hooks:
from bamengine import event, ops @event(after="firms_collect_revenue") class MyCustomEvent: def execute(self, sim): ext = sim.get_role("MyExtension") ops.assign(ext.custom_field, ...)
Bundle into an Extension for one-call activation:
from bamengine import Extension MY_EVENTS = [MyCustomEvent] MY_CONFIG = {"my_param": 0.5} MY_EXT = Extension( roles={MyExtension: "firms"}, events=MY_EVENTS, relationships=[], config_dict=MY_CONFIG, )
Activate in user code:
sim.use(MY_EXT)
See Custom Roles, Custom Events, and Configuration for detailed syntax.
See also
Custom Roles for defining extension roles
Custom Events for defining extension events
Pipeline Customization for understanding hook insertion points
Configuration for extension parameters (
extra_params)Validation & Analysis for validating extension behavior