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:

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:

  1. Define a role (if new state variables are needed):

    from bamengine import role
    from bamengine.typing import Float
    
    
    @role
    class MyExtension:
        custom_field: Float
    
  2. 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, ...)
    
  3. 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,
    )
    
  4. Activate in user code:

    sim.use(MY_EXT)
    

See Custom Roles, Custom Events, and Configuration for detailed syntax.

See also