An automated daily workflow that converts public energy market fundamentals into a desk-ready trading narrative for European power (Day-Ahead to curve).
european-risk-pack/
├── risk_monitor.py # Main automated pipeline
├── requirements.txt
├── .gitignore
├── README.md
├── desk_note/
│ └── desk_note.tex # LaTeX source for the 1–3 page desk note PDF
└── sample_outputs/ # Pre-generated artifacts (charts, brief, CSV)
├── chart_1_macro_drivers.png
├── chart_2_power_spreads.png
├── chart_3_spread_history.png
├── metrics_snapshot.csv
├── prompt_log.txt
└── daily_desk_brief.md
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtexport GEMINI_API_KEY="AIza..." # macOS / Linux
$env:GEMINI_API_KEY = "AIza..." # Windows PowerShellGet a free key at Google AI Studio. The script runs without a key — it skips only the AI narrative step.
python risk_monitor.pyAll outputs are written to ./output_artifacts/.
| # | Metric | Unit | Relevance |
|---|---|---|---|
| 1 | TTF Gas Front-Month | €/MWh | Primary gas prompt risk benchmark |
| 2 | EUA Carbon Front-Dec | €/t CO₂ | Carbon compliance cost signal |
| 3 | German Baseload Front-Month | €/MWh | European power curve proxy |
| 4 | EU Gas Storage Fill | % | Fundamental supply buffer; drives winter curve risk |
| 5 | Clean Spark Spread (CSS) | €/MWh | CCGT margin → gas-fired gen profitability |
| 6 | Clean Dark Spread (CDS) | €/MWh | Coal-plant margin → coal gen profitability |
| 7 | Coal-to-Gas Switching Price | €/tCO₂ | EUA threshold above which gas beats coal at the margin |
Bonus computed metrics (internal)
- Spark–Dark Differential (fuel-switching signal)
- Rolling 30-day Gas-on-Power beta
CSS = P_power − P_gas/η_gas − E_gas × P_carbon
CDS = P_power − P_coal/η_coal − E_coal × P_carbon
Coal-to-Gas Switching Price =
(P_gas/η_gas − P_coal/η_coal)
─────────────────────────────────────────────────
(E_coal/η_coal − E_gas/η_gas)
Where:
- η_gas = 0.50 (CCGT efficiency)
- η_coal = 0.35 (hard coal plant efficiency)
- E_gas = 0.20 tCO₂/MWh_thermal
- E_coal = 0.34 tCO₂/MWh_thermal
fetch_market_data() # Pulls / simulates OHLC for 5 commodities
↓
calculate_metrics() # Computes all 7 metrics + rolling beta
↓
build_metrics_snapshot() # Today vs prior day table → CSV
↓
generate_charts() # 3 production-quality charts
↓
generate_ai_narrative() # Gemini API → logs prompt + response → MD brief
The generate_ai_narrative() function:
- Structures the prompt with all 7 live metrics and a strict 2-paragraph template.
- Calls Gemini 2.5 Flash via the
google-genaiSDK. - Logs the full prompt and raw model response to
output_artifacts/prompt_log.txt. - Writes a formatted Markdown desk brief to
output_artifacts/daily_desk_brief.md.
This reduces the daily analyst write-up from ~20 minutes to under 30 seconds.
| Current (mock) | Production swap-in |
|---|---|
np.random simulation |
blpapi / refinitiv-data / Montel API |
| Single-day run | Cron job or Airflow DAG (daily 07:00 CET) |
| Gemini Flash | Any OpenAI / Anthropic / local LLM via same interface |
| Markdown output | Push to Confluence / email via SMTP / Slack webhook |
cd desk_note
pdflatex desk_note.tex
pdflatex desk_note.tex # second pass for referencesRequires a LaTeX distribution (TeX Live / MiKTeX). Charts must be generated first.