- Python 97.5%
- Jupyter Notebook 2.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Every scenario YAML in conf/scenario/ (36 files, e.g. oil_collapse_2014, covid_collapse_2020) defines its own shock volatilities, starting GDP/inflation/rates, and initial oil price to represent that episode or what-if -- but experiments/runner.py's _run_simulations() only ever read the energy_policy section (via _load_scenario_config() -> Scenario.get_policy_params()). The oil/shocks/initial_conditions sections were correctly parsed into the Scenario dataclass (scenario_registry.py has fields for all three) but never read back anywhere in this file, so every scenario silently ran with the same generic default shocks and starting conditions -- only the 4 energy-policy fields actually differed between scenarios, for the whole history of this code path. Verified concretely: oil_collapse_2014.yaml specifies initial_price: 52.0 and ca gdp: 1.95 (representing Dec 2014's actual price collapse), but before this fix the simulated oil_price[:, 0] was 80.0 (the generic default) and ca_gdp[:, 0] was 2.1 -- the scenario's entire premise was silently discarded. This affected Pipeline Analysis (Streamlit), and any CLI/ExperimentRunner-based run. The Hydra path (scripts/run_experiment.py, "recommended for research" per README) was NOT affected -- it already applies these fields correctly by mutating MC_CONFIG directly. Fixed via the same per-instance config-override mechanism used for PolicyOptimizer's phi_pi/phi_y earlier this session: extended POLICY_PARAM_TO_CONFIG_FIELD (monte_carlo/engine.py) with shock- volatility and initial-condition mappings using the same key names as each YAML's shocks:/initial_conditions: sections, and added _load_scenario_model_params() (experiments/runner.py) to flatten a scenario's full oil/shocks/initial_conditions into that shape and pass it through to get_optimal_simulator() alongside calibrated_params. Verified end-to-end: oil_collapse_2014 now starts at oil_price=52.0 / ca_gdp=1.95 as specified, and correctly shows 100% recession probability -- a real, economically meaningful result for that episode instead of a generic run indistinguishable from any other scenario except its energy-policy fields. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkkNxZSNBpstQGcgzCSnCZ |
||
| calibration | ||
| conf | ||
| config | ||
| data | ||
| docs | ||
| evaluation | ||
| examples | ||
| experiments | ||
| monte_carlo | ||
| notebooks | ||
| optimization | ||
| rl | ||
| scripts | ||
| tests | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| CONFIG.md | ||
| EXPLORATION.md | ||
| FUTURE_WORK.md | ||
| mypy.ini | ||
| pyproject.toml | ||
| pytest.ini | ||
| README.md | ||
| requirements.txt | ||
Canadian Energy Policy Macro Research Framework
A comprehensive DSGE-lite simulation framework for analyzing Canadian energy market policies and their macroeconomic implications.
Overview
This framework implements a research-grade macroeconomic simulation of the Canada-US economic relationship, with a focus on:
- Energy Market Policy Design: Testing national pipeline scenarios, regional decoupling, and renewable transitions
- Two-Country DSGE Model: Coupled Canada-US macroeconomic dynamics with trade, interest rate, and exchange rate linkages
- Optimal Monetary Policy: Pareto frontier analysis and RL-based policy learning under regime uncertainty
- Stress Testing: Oil price scenarios ($40-$150) and volatility regimes
Key Features
Recent Improvements
- Custom RL Configs (April 2026): Both
MacroEnvironmentandDQNAgentnow accept optionalconfigparameters for user-defined reward weights and policy targets - Enhanced State Space (April 2026 → September 2026): grew from 7 macro variables to 11 (7 macro + 4 energy) to the current 13-dimensional state (7 macro + 6 energy, adding
west_to_east_flowandrenewable_sharefor pipeline-integration and green-transition policy analysis) — seeRLConfig.STATE_DIMinconfig/simulation.py - Streamlit Upgrades (April 2026): 4 new advanced experiment modes added (Pareto Frontier, Stress Tests, Sensitivity, Convergence)
- Compute backend selection (September 2026):
monte_carlo.engine.get_optimal_simulator()picks MLX (Apple Silicon), CUDA (NVIDIA/cupy), or Numba/CPU automatically, or a specific backend can be forced — selectable live from the Streamlit sidebar
Model Architecture
- Modular Agent-Based Design: Household, firm, central bank, energy sector, and housing agents
- Vectorized Monte Carlo: Efficient parallel simulation of 1000s of paths
- GPU Acceleration: Optional CuPy support for large-scale experiments
- Two-Country Coupling: Endogenous trade flows, exchange rate dynamics, and interest spillovers
Energy Sector Modeling
- Regional split (East vs West Canada)
- Pipeline capacity and flow modeling
- Domestic vs export market dynamics
- Oil price pass-through to inflation and GDP
Policy Analysis
- Pareto Optimization: Tradeoff curves for recession risk vs inflation control
- RL-Based Policy: Deep Q-Networks learn optimal monetary policy under uncertainty
- Regime-Specific Calibration: Different optimal policies for high/low oil volatility
Exploration & Visualization
- Streamlit App: Interactive web interface with 11 modes:
- Quick Simulation, Pipeline Policy Analysis, Pareto Frontier Explorer
- Stress Test Suite, Sensitivity Analysis, Monte Carlo Convergence
- Energy Policy RL, Statistical Tests, Hydra Integration
- Load Results, Compare Scenarios
- Export Tools: Automated CSV/PNG export for papers and presentations
Installation
# Clone repository
git clone <repo-url>
cd macro-research-framework
# Install dependencies
pip install -r requirements.txt
# Optional: GPU support
pip install cupy-cuda11x # Adjust for your CUDA version
Quick Start
1. Run Data Pipeline
python scripts/cli.py pipeline --fred-key YOUR_FRED_API_KEY
2. Baseline Simulation
# Run 2000 Monte Carlo paths with default scenarios
python scripts/cli.py baseline --n-paths 2000 --pareto --rl
# High oil price scenario only
python scripts/cli.py baseline --scenarios high --n-paths 5000
3. Stress Testing
# Test multiple oil price levels
python scripts/cli.py stress-test --oil-prices 40 60 80 100 120 150
4. Pareto Frontier Optimization
# Compute optimal policy tradeoffs
python scripts/cli.py pareto --n-points 20 --n-paths 2000
5. RL Policy Training
# Train RL-based monetary policy
python scripts/cli.py rl --episodes 500
6. Energy Policy Comparison
# Compare different energy market designs
python scripts/cli.py energy-policy
7. Interactive Exploration (Streamlit)
# Launch interactive web app for exploring results
streamlit run scripts/app.py
# Or run example script to generate and export results
python examples/run_and_export.py
Streamlit Modes:
| Mode | Purpose | Best For |
|---|---|---|
| Quick Simulation | Fast single-scenario runs | Rapid iteration, parameter tuning |
| Pipeline Policy Analysis | East-west energy policy comparison | Canadian energy market design |
| Pareto Frontier Explorer | Multi-objective policy optimization | Finding optimal BoC policy tradeoffs |
| Stress Test Suite | Oil price & demand shock scenarios | Risk assessment, tail risk analysis |
| Sensitivity Analysis | Parameter sweep analysis | Model robustness testing |
| Monte Carlo Convergence | Path count validation | Ensuring simulation stability |
| Energy Policy RL | Train RL-based monetary policy | AI-driven policy optimization |
| Statistical Tests | Structural break & coverage tests | Model validation |
| Hydra Experiment | Preview Hydra configurations | Pre-run config validation |
| Load Results | View saved experiments | Post-hoc analysis |
| Compare Scenarios | Side-by-side scenario comparison | Policy briefings |
Example - Pareto Frontier Analysis:
streamlit run scripts/app.py
# Select "Pareto Frontier Explorer"
# Adjust: 2000 paths, 10 frontier points
# Explore tradeoff between recession risk and inflation control
# Export optimal policy parameters as CSV
Example - Stress Testing:
streamlit run scripts/app.py
# Select "Stress Test Suite"
# Configure oil prices: $40, $60, $80, $100, $120
# Run 5000 paths per scenario
# Compare GDP trajectories under stress
8. Hydra Configuration (Recommended for Research)
# Run with default configuration
python scripts/run_experiment.py
# Run specific scenario with specific policy
python scripts/run_experiment.py scenario=high_oil model=aggressive
# Run large-scale simulation
python scripts/run_experiment.py simulation=large_scale
# Run parameter sweep (multirun)
python scripts/run_experiment.py --multirun scenario=baseline,low_oil,high_oil
# Run full grid search: 3 scenarios × 3 models
python scripts/run_experiment.py --multirun scenario=baseline,low_oil,high_oil model=standard_taylor,aggressive,accommodative
# Override specific parameters
python scripts/run_experiment.py scenario=high_oil simulation.n_paths=5000 experiment.seed=123
# Add verbose output
python scripts/run_experiment.py scenario=high_oil experiment.verbose=true
All outputs automatically saved to timestamped directories under results/.
See conf/ directory for all configurable options.
Framework Structure
macro-research-framework/
├── scripts/ # Executable entry points
│ ├── cli.py # Typer CLI (baseline, stress-test, pareto, rl)
│ ├── run_experiment.py # Hydra experiment runner (recommended)
│ ├── run_pipeline_analysis.py # Pipeline policy analysis
│ ├── app.py # Streamlit web interface
│ └── diagnostics/ # Ad-hoc dev scripts (not the pytest suite — see tests/)
├── conf/ # Hydra hierarchical configs
│ ├── config.yaml # Main experiment configuration
│ ├── scenario/ # Scenario configs (36 YAML files)
│ ├── model/ # Model configs (taylor_rule variants)
│ └── simulation/ # Simulation configs (default, large_scale)
├── config/
│ └── simulation.py # Pydantic configs (MC_CONFIG, RL_CONFIG, etc.)
├── monte_carlo/
│ └── engine.py # Vectorized/GPU Monte Carlo simulator
├── rl/
│ ├── agent.py # DQN agent for monetary policy
│ ├── environment.py # Macro RL environment
│ └── trainer.py # RL training and evaluation
├── optimization/
│ └── pareto.py # Pareto frontier optimizer
├── data/
│ ├── pipeline.py # FRED + StatsCan ETL (uses Polars)
│ └── async_pipeline.py # Async data loading helpers
├── calibration/
│ ├── elasticities.py # Elasticity estimation
│ └── taylor_rule.py # Taylor rule calibration
├── experiments/
│ ├── runner.py # Experiment orchestration
│ ├── scenario_registry.py # Scenario metadata registry
│ └── pipeline_analysis.py # Pipeline policy analysis
├── examples/
│ └── run_and_export.py # Example: Run & export experiments
├── notebooks/
│ └── exploration.ipynb # Jupyter notebook for analysis
├── tests/ # pytest test suite
├── requirements.txt # Package versions
├── pyproject.toml # Modern Python packaging
├── README.md # This file
└── EXPLORATION.md # Guide to exploration tools
Research Applications
1. Energy Market Design
Test whether a national east-west pipeline would reduce Canadian exposure to global oil price volatility:
from model.country import TwoCountryModel
# Create model with pipeline
model = TwoCountryModel(canada_params, us_params)
model.canada.build_energy_pipeline()
# Run simulation
results = model.simulate(T=40)
2. Policy Tradeoff Analysis
Find Pareto-optimal BoC policy parameters:
from optimization.pareto import PolicyOptimizer
optimizer = PolicyOptimizer(simulator, params)
frontier = optimizer.compute_pareto_frontier(n_points=20)
# Get optimal tradeoff
optimal = optimizer.find_optimal_tradeoff(
target_recession=0.15,
target_inflation=0.015
)
3. Regime-Dependent Policy
Train RL agent that adapts to different oil volatility regimes:
from optimization.rl_policy import RLPolicyOptimizer
rl_opt = RLPolicyOptimizer()
rl_opt.train(n_episodes=500)
# Compare with Taylor rule
results = rl_opt.compare_policies()
Model Calibration
Key calibrated parameters (from historical data):
| Parameter | Value | Source |
|---|---|---|
| Oil-GDP elasticity (Canada) | ~0.12 | StatsCan 2000-2023 |
| Oil-inflation elasticity | ~0.08 | BoC CPI decomposition |
| US spillover to Canada | ~0.35 | FRED + StatsCan |
| BoC Taylor rule: φ_π | ~1.6 | Rolling estimation |
| BoC Taylor rule: φ_y | ~0.4 | Rolling estimation |
Stress Test Results
Example output from $40 vs $120 oil price scenarios:
| Metric | $40 Oil | $120 Oil |
|---|---|---|
| Mean GDP Growth | 1.2% | 2.8% |
| Recession Probability | 28% | 12% |
| Mean Inflation | 1.5% | 3.2% |
| CAD/USD | 0.68 | 0.82 |
| House Price Growth | -2% | +8% |
Academic Citation
If using this framework for research:
@software{macro_energy_framework,
title = {Canadian Energy Policy Macro Research Framework},
author = {[Author]},
year = {2024},
url = {[Repository URL]}
}
License
MIT License - See LICENSE file
Contact
For questions or collaboration: [email]