Skip to main content

Open, reproducible pipeline for EU Emissions Trading System analysis from free public data

Project description

carbon-ets

CI Python License: MIT Open In Colab

Open, reproducible pipeline for EU Emissions Trading System (EU ETS) analysis from free public data.

Everything runs on published, non-paywalled sources: EEX primary-auction clearing prices, Eurostat industrial production, European Commission MSR Communications, and Open-Meteo weather. Free replacement for ~€20-50k/year of paid EU ETS data infrastructure.

Companion code to Causal Systems research report Factories to carbon.

Try it in 30 seconds: click the "Open in Colab" badge above.

What's in the box

  • Historical EUA prices 2012-present — daily primary auction clearing prices scraped from EEX archive
  • Eurostat industrial production — via SDMX bulk endpoint with JSON-stat fallback
  • TNAC reference series 2016-2025 — verified values from every Commission Communication PDF, with primary-source citations
  • MSR mechanism helpers — thresholds, invalidation history, regime-context lookup for any TNAC value
  • Feature engineering — log returns, z-scores, momentum, realised volatility, IP YoY
  • V1 baseline backtest — long-only causal-chain strategy from the CS/RES/05 report
  • Markov-switching regression — two-regime model for EUA return dynamics (descriptive, not predictive)
  • Standard plots — equity curves, TNAC history with MSR thresholds, regime diagnostics

What's NOT in v0.1

Being explicit about scope. We removed features that failed our internal validation rather than shipping them broken:

  • Monthly TNAC nowcast — validated at 20%+ median error against Commission-published values, well outside a defensible confidence band. Planned for v0.2 once we wire in real EUTL per-year data.
  • Compliance-buy timing signal — tested empirically and does not persistently outperform naive strategies.
  • Sector transmission model — regressions of Rotterdam-cluster equities on EUA did not clear statistical significance.

Choosing to ship less rather than ship broken is the design principle here.

Install

pip install carbon-ets              # core (no yfinance)
pip install carbon-ets[yfinance]    # with Yahoo Finance for equity/gas proxies
pip install carbon-ets[all]         # everything including Jupyter

Or from source:

git clone https://github.com/causalsystems-co/carbon-ets
cd carbon-ets
pip install -e .[all]

Quickstart

from carbon_ets.data import build_full_panel
from carbon_ets.features import engineer
from carbon_ets.models import backtest_v1
from carbon_ets.tnac import nowcast_monthly

panel = build_full_panel(start="2012-01-01")
feats = engineer(panel)
stats, equity = backtest_v1(feats)
print(f"Sharpe = {stats['sharpe']:.2f}, CAGR = {stats['cagr']:+.1%}")

# Current TNAC nowcast — updated as new data arrives
tnac = nowcast_monthly()
print(f"Estimated TNAC ({tnac.as_of.date()}): {tnac.tnac_estimate:,.0f} allowances")

See examples/quickstart.py for the full end-to-end run.

What's honest about this

This toolkit does not claim to be a trading system. The backtest returns you see are:

  • In-sample and window-dependent — Sharpe 0.8-1.0 on 2015-2024 EUA settlement data, but not tested out-of-sample
  • Sensitive to feature specification — different regime interpretations arise from different feature sets
  • Not corrected for realistic transaction costs, slippage, or execution frictions

The toolkit is designed for research and policy analysis, not live trading. If you want to trade EUA, you need paid data feeds, a proper execution stack, and independent validation.

The core empirical finding — that the demand-side chain explains ~5% of monthly variance on average and up to 63% in specific windows — is reproducible from the pipeline and is the piece worth citing.

Architecture

carbon_ets/
├── data.py         — EEX auction fetcher, Eurostat SDMX, panel builder
├── features.py     — engineered features (returns, z-scores, momentum, vol)
├── models.py       — backtest_v1, Markov-switching MS-2 wrapper
├── tnac.py         — hardcoded TNAC series + monthly nowcast + validation
├── plots.py        — equity curves, TNAC diagnostics
└── __init__.py

examples/
└── quickstart.py   — end-to-end reproducibility

pyproject.toml      — package config, dependencies

Contributing

Issues and pull requests welcome, especially:

  • Data gap fills — missing pre-2013 auction data, alternative EUA proxies (KEUA, CFI), or additional emissions data sources
  • Feature ideas — CBAM import volumes, ETS2 preparation data, sector-specific compliance proxies
  • Method extensions — regime-switching alternatives, structural VAR, natural experiments around MSR events
  • Cross-market ports — California CCA (CARB), UK ETS, RGGI applications of the same architecture

Citing

If you use this in published work, please cite:

Causal Systems (2026). Factories to carbon: a demand-side model of EU allowance prices. CS/RES/05. https://causalsystems.co/research/factories-to-carbon

License

MIT. See LICENSE.

Contact

hello@causalsystems.co

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

carbon_ets-0.1.0.tar.gz (20.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

carbon_ets-0.1.0-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

File details

Details for the file carbon_ets-0.1.0.tar.gz.

File metadata

  • Download URL: carbon_ets-0.1.0.tar.gz
  • Upload date:
  • Size: 20.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for carbon_ets-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2820607e5ba6e28bc1b7bd24adb26ee1bf998e5f9d0c7e26716cf40afb3fb9a3
MD5 7f0d7b1b4f45acb353370f1a8811d254
BLAKE2b-256 f008e5d3d02fc10b222ac13f97596766b5fb19a852cbdd15f6cf5f7ca5dd3316

See more details on using hashes here.

File details

Details for the file carbon_ets-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: carbon_ets-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 17.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for carbon_ets-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aeb66b13d8c264026b22053908c269fba24868e1c11a46aa68873f08e108f472
MD5 94915d28653a8aaec82d101f478bcfbd
BLAKE2b-256 1a70a75250049e7a536eb4dfa813196478b02bf87b2651bb2485494715a4fcf7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page