.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/basic/example_baseline_scenario.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_basic_example_baseline_scenario.py: =============================== BAM Baseline Scenario =============================== This example reproduces the baseline scenario from section 3.9.1 of the original BAM model book (Delli Gatti et al., 2011). This scenario demonstrates the fundamental dynamics of the model with standard parameter values. We visualize eight panels: four time series (real GDP, unemployment rate, inflation rate, productivity-real wage) and four macroeconomic curves (Phillips, Okun, Beveridge, and firm size distribution). For detailed validation with bounds and statistical annotations, run: python -m validation.scenarios.baseline .. GENERATED FROM PYTHON SOURCE LINES 19-23 Initialize Simulation ----------------------------- Create a simulation using default parameters that correspond to the baseline scenario. .. GENERATED FROM PYTHON SOURCE LINES 23-34 .. code-block:: Python import bamengine as bam from bamengine import ops sim = bam.Simulation.init() print("Initialized baseline scenario with:") print(f" - {sim.n_firms} firms") print(f" - {sim.n_households} households") print(f" - {sim.n_banks} banks") .. rst-class:: sphx-glr-script-out .. code-block:: none Initialized baseline scenario with: - 100 firms - 500 households - 10 banks .. GENERATED FROM PYTHON SOURCE LINES 35-39 Run Simulation -------------- Run with data collection for key economic indicators. .. GENERATED FROM PYTHON SOURCE LINES 39-61 .. code-block:: Python COLLECT_CONFIG = { "Producer": ["production", "labor_productivity"], "Worker": ["wage", "employed"], "Employer": ["n_vacancies"], "capture_timing": { # Capture wages after workers receive them (not stale previous-period value) "Worker.wage": "workers_receive_wage", # Capture employment after production (steady-state, before bankruptcy resets) "Worker.employed": "firms_run_production", # Capture production after it happens "Producer.production": "firms_run_production", # Capture vacancies right after firms decide them "Employer.n_vacancies": "firms_decide_vacancies", }, } results = sim.run(collect=COLLECT_CONFIG) print(f"\nSimulation completed: {results.metadata['n_periods']} periods") print(f"Runtime: {results.metadata['runtime_seconds']:.2f} seconds") .. rst-class:: sphx-glr-script-out .. code-block:: none Simulation completed: 1000 periods Runtime: 5.44 seconds .. GENERATED FROM PYTHON SOURCE LINES 62-66 Compute Metrics --------------- Compute key economic indicators from the simulation results. .. GENERATED FROM PYTHON SOURCE LINES 66-147 .. code-block:: Python import numpy as np burn_in = 500 n_periods = sim.n_periods # Extract raw data from results avg_price = results["Economy.avg_price"] production = results.get("Producer", "production") productivity = results.get("Producer", "labor_productivity") wages = results.get("Worker", "wage") employed_arr = results.get("Worker", "employed") n_vacancies = results.get("Employer", "n_vacancies") # Compute total production (GDP) total_production = ops.sum(production, axis=1) # Unemployment rate (fraction of workers not employed) unemployment = 1 - ops.mean(employed_arr.astype(float), axis=1) # Log GDP log_gdp = ops.log(total_production + 1e-10) # Annual inflation rate inflation = results["Economy.inflation"] # Average wage for employed workers employed_wages_sum = ops.sum(ops.where(employed_arr, wages, 0.0), axis=1) employed_count = ops.sum(employed_arr, axis=1) avg_wage = ops.where( ops.greater(employed_count, 0), ops.divide(employed_wages_sum, employed_count), 0.0, ) # Real wage real_wage = ops.divide(avg_wage, avg_price) # Production-weighted average productivity weighted_prod = ops.sum(ops.multiply(productivity, production), axis=1) avg_productivity = ops.divide(weighted_prod, total_production) # Wage inflation for Phillips curve wage_inflation = ops.divide( avg_wage[1:] - avg_wage[:-1], ops.where(ops.greater(avg_wage[:-1], 0), avg_wage[:-1], 1.0), ) # GDP growth for Okun curve gdp_growth = ops.divide( total_production[1:] - total_production[:-1], total_production[:-1] ) # Unemployment growth for Okun curve unemployment_growth = ops.divide( unemployment[1:] - unemployment[:-1], ops.where(ops.greater(unemployment[:-1], 0), unemployment[:-1], 1.0), ) # Vacancy rate for Beveridge curve total_vacancies = ops.sum(n_vacancies, axis=1) vacancy_rate = ops.divide(total_vacancies, sim.n_households) # Final period firm production prod = sim.get_role("Producer") final_production = prod.production.copy() # Correlations phillips_corr = np.corrcoef(unemployment[burn_in:], wage_inflation[burn_in - 1 :])[0, 1] okun_corr = np.corrcoef(unemployment_growth[burn_in - 1 :], gdp_growth[burn_in - 1 :])[ 0, 1 ] beveridge_corr = np.corrcoef(unemployment[burn_in:], vacancy_rate[burn_in:])[0, 1] print(f"\nKey metrics (after {burn_in}-period burn-in):") print(f" Unemployment: {np.mean(unemployment[burn_in:]) * 100:.1f}%") print(f" Inflation: {np.mean(inflation[burn_in:]) * 100:.1f}%") print(f" Phillips correlation: {phillips_corr:.2f}") print(f" Okun correlation: {okun_corr:.2f}") print(f" Beveridge correlation: {beveridge_corr:.2f}") .. rst-class:: sphx-glr-script-out .. code-block:: none Key metrics (after 500-period burn-in): Unemployment: 6.0% Inflation: 1.1% Phillips correlation: -0.42 Okun correlation: -0.76 Beveridge correlation: -0.32 .. GENERATED FROM PYTHON SOURCE LINES 148-152 Visualize Results ----------------- Create a simple 4x2 figure showing time series and macroeconomic curves. .. GENERATED FROM PYTHON SOURCE LINES 152-252 .. code-block:: Python import matplotlib.pyplot as plt periods = ops.arange(burn_in, n_periods) fig, axes = plt.subplots(4, 2, figsize=(14, 20)) fig.suptitle("BAM Model Baseline Scenario (Section 3.9.1)", fontsize=16, y=0.995) # Panel (0,0): Log Real GDP ax = axes[0, 0] ax.plot(periods, log_gdp[burn_in:], linewidth=1, color="#2E86AB") ax.set_title("Real GDP", fontsize=12, fontweight="bold") ax.set_ylabel("Log output") ax.set_xlabel("t") ax.grid(True, linestyle="--", alpha=0.3) # Panel (0,1): Unemployment Rate ax = axes[0, 1] ax.plot(periods, unemployment[burn_in:] * 100, linewidth=1, color="#A23B72") ax.set_title("Unemployment Rate", fontsize=12, fontweight="bold") ax.set_ylabel("Unemployment Rate (%)") ax.set_xlabel("t") ax.set_ylim(bottom=0) ax.grid(True, linestyle="--", alpha=0.3) # Panel (1,0): Annual Inflation Rate (all periods, x-axis in cumulated years) ax = axes[1, 0] years = ops.arange(0, n_periods) / 4 ax.plot(years, inflation * 100, linewidth=1, color="#F18F01") ax.axhline(0, color="black", linestyle="-", alpha=0.3, linewidth=0.5) ax.set_title("Annualized Rate of Inflation", fontsize=12, fontweight="bold") ax.set_ylabel("Yearly inflation rate (%)") ax.set_xlabel("Years (cumulated quarters)") ax.grid(True, linestyle="--", alpha=0.3) # Panel (1,1): Productivity and Real Wage (with legend) ax = axes[1, 1] ax.plot( periods, avg_productivity[burn_in:], linewidth=1, color="#E74C3C", label="Productivity", ) ax.plot(periods, real_wage[burn_in:], linewidth=1, color="#6A994E", label="Real Wage") ax.set_title("Productivity / Real Wage", fontsize=12, fontweight="bold") ax.set_ylabel("Value") ax.set_xlabel("t") ax.legend(loc="center right", fontsize=8) ax.grid(True, linestyle="--", alpha=0.3) # Panel (2,0): Phillips Curve ax = axes[2, 0] ax.scatter( unemployment[burn_in:], wage_inflation[burn_in - 1 :], s=10, alpha=0.5, color="#2E86AB", ) ax.set_title(f"Phillips Curve (r={phillips_corr:.2f})", fontsize=12, fontweight="bold") ax.set_xlabel("Unemployment Rate") ax.set_ylabel("Wage Inflation Rate") ax.grid(True, linestyle="--", alpha=0.3) # Panel (2,1): Okun Curve ax = axes[2, 1] ax.scatter( unemployment_growth[burn_in - 1 :], gdp_growth[burn_in - 1 :], s=2, alpha=0.5, color="#A23B72", ) ax.set_title(f"Okun Curve (r={okun_corr:.2f})", fontsize=12, fontweight="bold") ax.set_xlabel("Unemployment Growth Rate") ax.set_ylabel("Output Growth Rate") ax.grid(True, linestyle="--", alpha=0.3) # Panel (3,0): Beveridge Curve ax = axes[3, 0] ax.scatter( unemployment[burn_in:], vacancy_rate[burn_in:], s=10, alpha=0.5, color="#F18F01" ) ax.set_title( f"Beveridge Curve (r={beveridge_corr:.2f})", fontsize=12, fontweight="bold" ) ax.set_xlabel("Unemployment Rate") ax.set_ylabel("Vacancy Rate") ax.grid(True, linestyle="--", alpha=0.3) # Panel (3,1): Firm Size Distribution ax = axes[3, 1] ax.hist(final_production, bins=10, edgecolor="black", alpha=0.7, color="#6A994E") ax.set_title("Firm Size Distribution", fontsize=12, fontweight="bold") ax.set_xlabel("Production") ax.set_ylabel("Frequency") ax.grid(True, linestyle="--", alpha=0.3) plt.tight_layout() plt.show() .. image-sg:: /auto_examples/basic/images/sphx_glr_example_baseline_scenario_001.png :alt: BAM Model Baseline Scenario (Section 3.9.1), Real GDP, Unemployment Rate, Annualized Rate of Inflation, Productivity / Real Wage, Phillips Curve (r=-0.42), Okun Curve (r=-0.76), Beveridge Curve (r=-0.32), Firm Size Distribution :srcset: /auto_examples/basic/images/sphx_glr_example_baseline_scenario_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 6.131 seconds) .. _sphx_glr_download_auto_examples_basic_example_baseline_scenario.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: example_baseline_scenario.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: example_baseline_scenario.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: example_baseline_scenario.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_