Spaces:
Sleeping
Sleeping
Commit ·
2009f7f
0
Parent(s):
Deploy clean Space (no binary artifacts)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +3 -0
- .gitignore +15 -0
- Dockerfile +28 -0
- README.md +8 -0
- app/main.py +256 -0
- app/main2.py +105 -0
- entrypoint.sh +104 -0
- model/costs/capex/capex.py +84 -0
- model/costs/capex/capex_mod.py +169 -0
- model/costs/capex/other_costs.csv +7 -0
- model/costs/finance/finance.py +67 -0
- model/costs/finance/finance_mod.py +192 -0
- model/costs/opex/opex.csv +3 -0
- model/costs/opex/opex.py +35 -0
- model/costs/opex/opex_mod.py +86 -0
- model/costs/planning/merge.py +38 -0
- model/costs/planning/national_project_development_costs.csv +4 -0
- model/costs/planning/national_wind_project_development_costs.csv +5 -0
- model/costs/planning/permitting_phase_bundesland.csv +16 -0
- model/costs/planning/planning_phase_bundesland.csv +16 -0
- model/costs/planning/total_bundesland.csv +16 -0
- model/park_gross_mwh_monthly_mock_2015_2046.csv +385 -0
- model/profit.py +344 -0
- model/revenue/capture_factor_history_forecast/capture_factor_forecast_b2.csv +373 -0
- model/revenue/capture_factor_history_forecast/capture_factor_monthly_historical.csv +133 -0
- model/revenue/capture_factor_history_forecast/cf_his.py +96 -0
- model/revenue/capture_factor_history_forecast/reg_cf.py +182 -0
- model/revenue/curltailment_rate_per_tso/50Hertz1518.csv +0 -0
- model/revenue/curltailment_rate_per_tso/50Hertz1922.csv +0 -0
- model/revenue/curltailment_rate_per_tso/Amprion1518.csv +0 -0
- model/revenue/curltailment_rate_per_tso/Amprion1922.csv +0 -0
- model/revenue/curltailment_rate_per_tso/Tennet1518.csv +0 -0
- model/revenue/curltailment_rate_per_tso/Tennet1922.csv +0 -0
- model/revenue/curltailment_rate_per_tso/TransnetBW1518.csv +0 -0
- model/revenue/curltailment_rate_per_tso/TransnetBW1922.csv +0 -0
- model/revenue/curltailment_rate_per_tso/curltailment_rate_quarterly_by_tso.csv +31 -0
- model/revenue/curltailment_rate_per_tso/curltailmentcalc.py +103 -0
- model/revenue/curltailment_rate_per_tso/curtailment.csv +31 -0
- model/revenue/curltailment_rate_per_tso/curtailment_forecast_quarterly_by_tso_2021_2046.csv +417 -0
- model/revenue/curltailment_rate_per_tso/merge.py +106 -0
- model/revenue/curltailment_rate_per_tso/pred_cr.py +175 -0
- model/revenue/curltailment_rate_per_tso/wind_onshore_daily_by_tso.csv +0 -0
- model/revenue/day_ahead_market_prices/eh1516.csv +0 -0
- model/revenue/day_ahead_market_prices/eh1718.csv +0 -0
- model/revenue/day_ahead_market_prices/eh1920.csv +0 -0
- model/revenue/day_ahead_market_prices/eh2122.csv +0 -0
- model/revenue/day_ahead_market_prices/eh2324.csv +0 -0
- model/revenue/day_ahead_market_prices/eh25.csv +0 -0
- model/revenue/day_ahead_market_prices/market_price_forecast_20y_monthly.csv +241 -0
- model/revenue/day_ahead_market_prices/market_price_monthly_history.csv +133 -0
.gitattributes
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
backend/model/revenue/mc_inputs_30y_monthly_merged.csv filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
frontend/src/data/GER_NUTS3_TSOs.shp filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
frontend/src/data/tso.json filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# venv / local artifacts
|
| 2 |
+
.venv/
|
| 3 |
+
venv/
|
| 4 |
+
**/.venv/
|
| 5 |
+
**/venv/
|
| 6 |
+
__pycache__/
|
| 7 |
+
*.pyc
|
| 8 |
+
|
| 9 |
+
# model binaries
|
| 10 |
+
wind-power-climate-ml/LGBM_Model/model_artifacts/
|
| 11 |
+
*.pkl
|
| 12 |
+
*.joblib
|
| 13 |
+
|
| 14 |
+
# optional: trash / outputs
|
| 15 |
+
model/revenue/trash/
|
Dockerfile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.9-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
ENV PIP_NO_CACHE_DIR=1 \
|
| 6 |
+
PYTHONDONTWRITEBYTECODE=1 \
|
| 7 |
+
PYTHONUNBUFFERED=1
|
| 8 |
+
|
| 9 |
+
# Falls du lightgbm / netcdf etc. nutzt, brauchst du evtl. Systemlibs.
|
| 10 |
+
# Minimal (häufig nötig für lightgbm): gcc/g++ und libgomp
|
| 11 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 12 |
+
gcc g++ libgomp1 \
|
| 13 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 14 |
+
|
| 15 |
+
# Python deps zuerst (besserer Docker cache)
|
| 16 |
+
COPY wind-power-climate-ml/requirements.txt /app/requirements.txt
|
| 17 |
+
RUN pip install -r /app/requirements.txt
|
| 18 |
+
RUN pip install -U huggingface_hub
|
| 19 |
+
|
| 20 |
+
# App-Code
|
| 21 |
+
COPY wind-power-climate-ml /app/wind-power-climate-ml
|
| 22 |
+
|
| 23 |
+
# Entrypoint
|
| 24 |
+
COPY entrypoint.sh /app/entrypoint.sh
|
| 25 |
+
RUN chmod +x /app/entrypoint.sh
|
| 26 |
+
|
| 27 |
+
EXPOSE 7860
|
| 28 |
+
CMD ["/app/entrypoint.sh"]
|
README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: windproject
|
| 3 |
+
sdk: docker
|
| 4 |
+
app_port: 7860
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
Wind Energy Forecast API
|
| 8 |
+
|
app/main.py
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, HTTPException
|
| 2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
from fastapi.responses import Response
|
| 4 |
+
from pydantic import BaseModel, Field
|
| 5 |
+
from typing import Optional, Any
|
| 6 |
+
import pandas as pd
|
| 7 |
+
import numpy as np
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
import sys
|
| 10 |
+
import json
|
| 11 |
+
import math
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
# --- Make sure Python can import from backend/model ---
|
| 15 |
+
# project/backend/app/main.py -> project/backend
|
| 16 |
+
BACKEND_ROOT = Path(__file__).resolve().parents[1]
|
| 17 |
+
MODEL_DIR = BACKEND_ROOT / "model"
|
| 18 |
+
sys.path.insert(0, str(MODEL_DIR))
|
| 19 |
+
|
| 20 |
+
# Now we can import your script
|
| 21 |
+
from profit import power_to_profit, FORECAST_MONTHS
|
| 22 |
+
|
| 23 |
+
app = FastAPI()
|
| 24 |
+
|
| 25 |
+
@app.get("/favicon.ico")
|
| 26 |
+
def favicon():
|
| 27 |
+
return Response(status_code=204)
|
| 28 |
+
|
| 29 |
+
@app.get("/")
|
| 30 |
+
def root():
|
| 31 |
+
return {"ok": True, "message": "Backend running. Go to /docs for API docs."}
|
| 32 |
+
|
| 33 |
+
# Allow the Vite dev server to call the API from the browser during development.
|
| 34 |
+
app.add_middleware(
|
| 35 |
+
CORSMiddleware,
|
| 36 |
+
allow_origins=["*"], # allow all origins for testing
|
| 37 |
+
allow_credentials=True,
|
| 38 |
+
allow_methods=["*"],
|
| 39 |
+
allow_headers=["*"],
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
# -------------------------
|
| 43 |
+
# Request schema
|
| 44 |
+
# -------------------------
|
| 45 |
+
class CalcRequest(BaseModel):
|
| 46 |
+
# Settings from the UI
|
| 47 |
+
n_turbines: int = Field(ge=1)
|
| 48 |
+
hub_height_m: int = Field(ge=1)
|
| 49 |
+
turbine_type_id: int = Field(ge=0, le=2)
|
| 50 |
+
equity_eur: int = Field(ge=0)
|
| 51 |
+
|
| 52 |
+
# Revenue module required keys
|
| 53 |
+
tso_id: int = Field(ge=0, le=3)
|
| 54 |
+
eeg_on: bool
|
| 55 |
+
cod_date: str # "YYYY-MM-DD"
|
| 56 |
+
manual_eeg_strike: Optional[float] = None
|
| 57 |
+
|
| 58 |
+
# For now: constant monthly MWh (easy to wire first)
|
| 59 |
+
mwh_constant: float = Field(gt=0)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def to_jsonable(obj: Any):
|
| 63 |
+
"""Convert pandas/numpy objects into JSON-serializable Python types.
|
| 64 |
+
Also replaces NaN/Inf with None (JSON-compliant).
|
| 65 |
+
"""
|
| 66 |
+
# pandas DataFrame
|
| 67 |
+
if isinstance(obj, pd.DataFrame):
|
| 68 |
+
df = obj.copy()
|
| 69 |
+
|
| 70 |
+
# Convert datetime columns to strings
|
| 71 |
+
for col in df.columns:
|
| 72 |
+
if pd.api.types.is_datetime64_any_dtype(df[col]):
|
| 73 |
+
df[col] = df[col].astype(str)
|
| 74 |
+
|
| 75 |
+
# Replace inf/-inf with NaN, then NaN -> None
|
| 76 |
+
df = df.replace([np.inf, -np.inf], np.nan)
|
| 77 |
+
df = df.where(pd.notnull(df), None)
|
| 78 |
+
|
| 79 |
+
return df.to_dict(orient="records")
|
| 80 |
+
|
| 81 |
+
# pandas Series
|
| 82 |
+
if isinstance(obj, pd.Series):
|
| 83 |
+
s = obj.copy()
|
| 84 |
+
|
| 85 |
+
# If index is datetime, return list of {date, value}
|
| 86 |
+
if pd.api.types.is_datetime64_any_dtype(s.index):
|
| 87 |
+
out = []
|
| 88 |
+
for idx, val in s.items():
|
| 89 |
+
if pd.isna(val) or val in (np.inf, -np.inf):
|
| 90 |
+
v = None
|
| 91 |
+
else:
|
| 92 |
+
v = float(val)
|
| 93 |
+
out.append({"date": str(idx), "value": v})
|
| 94 |
+
return out
|
| 95 |
+
|
| 96 |
+
# otherwise just list values
|
| 97 |
+
out = []
|
| 98 |
+
for x in s.to_list():
|
| 99 |
+
if pd.isna(x) or x in (np.inf, -np.inf):
|
| 100 |
+
out.append(None)
|
| 101 |
+
else:
|
| 102 |
+
out.append(float(x))
|
| 103 |
+
return out
|
| 104 |
+
|
| 105 |
+
# pandas Timestamp
|
| 106 |
+
if isinstance(obj, pd.Timestamp):
|
| 107 |
+
return str(obj)
|
| 108 |
+
|
| 109 |
+
# numpy scalars/arrays
|
| 110 |
+
if isinstance(obj, (np.integer,)):
|
| 111 |
+
return int(obj)
|
| 112 |
+
|
| 113 |
+
if isinstance(obj, (np.floating,)):
|
| 114 |
+
val = float(obj)
|
| 115 |
+
if val != val or val in (float("inf"), float("-inf")):
|
| 116 |
+
return None
|
| 117 |
+
return val
|
| 118 |
+
|
| 119 |
+
if isinstance(obj, np.ndarray):
|
| 120 |
+
# Convert elements too (in case the array has NaN)
|
| 121 |
+
return [to_jsonable(x) for x in obj.tolist()]
|
| 122 |
+
|
| 123 |
+
# plain Python float NaN/Inf
|
| 124 |
+
if isinstance(obj, float):
|
| 125 |
+
if obj != obj or obj in (float("inf"), float("-inf")):
|
| 126 |
+
return None
|
| 127 |
+
return obj
|
| 128 |
+
|
| 129 |
+
# dict / list / tuple
|
| 130 |
+
if isinstance(obj, dict):
|
| 131 |
+
return {k: to_jsonable(v) for k, v in obj.items()}
|
| 132 |
+
|
| 133 |
+
if isinstance(obj, (list, tuple)):
|
| 134 |
+
return [to_jsonable(x) for x in obj]
|
| 135 |
+
|
| 136 |
+
return obj
|
| 137 |
+
|
| 138 |
+
def scrub_nonfinite(obj: Any):
|
| 139 |
+
"""Recursively replace NaN/Inf/-Inf with None in already JSON-like objects."""
|
| 140 |
+
# dict
|
| 141 |
+
if isinstance(obj, dict):
|
| 142 |
+
return {k: scrub_nonfinite(v) for k, v in obj.items()}
|
| 143 |
+
|
| 144 |
+
# list/tuple
|
| 145 |
+
if isinstance(obj, (list, tuple)):
|
| 146 |
+
return [scrub_nonfinite(v) for v in obj]
|
| 147 |
+
|
| 148 |
+
# numpy scalar that may still exist
|
| 149 |
+
if isinstance(obj, np.generic):
|
| 150 |
+
return scrub_nonfinite(obj.item())
|
| 151 |
+
|
| 152 |
+
# float NaN/Inf
|
| 153 |
+
if isinstance(obj, float):
|
| 154 |
+
return None if not math.isfinite(obj) else obj
|
| 155 |
+
|
| 156 |
+
return obj
|
| 157 |
+
|
| 158 |
+
def pick_first_col(df: pd.DataFrame, candidates: list[str]) -> str | None:
|
| 159 |
+
for c in candidates:
|
| 160 |
+
if c in df.columns:
|
| 161 |
+
return c
|
| 162 |
+
return None
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
@app.post("/api/calc")
|
| 168 |
+
def calc(req: CalcRequest):
|
| 169 |
+
try:
|
| 170 |
+
# Build monthly MWh series for 20 years
|
| 171 |
+
cod = pd.Timestamp(req.cod_date)
|
| 172 |
+
cod = pd.Timestamp(year=cod.year, month=cod.month, day=1)
|
| 173 |
+
|
| 174 |
+
dates = pd.date_range(cod, periods=FORECAST_MONTHS, freq="MS")
|
| 175 |
+
mwh_series = pd.Series(float(req.mwh_constant), index=dates)
|
| 176 |
+
|
| 177 |
+
result = power_to_profit(
|
| 178 |
+
mwh_monthly_20y=mwh_series,
|
| 179 |
+
turbine_type_id=req.turbine_type_id,
|
| 180 |
+
n_turbines=req.n_turbines,
|
| 181 |
+
hub_height_m=req.hub_height_m,
|
| 182 |
+
equity_eur=float(req.equity_eur),
|
| 183 |
+
revenue_kwargs={
|
| 184 |
+
"tso_id": int(req.tso_id),
|
| 185 |
+
"eeg_on": 1 if req.eeg_on else 0,
|
| 186 |
+
"manual_eeg_strike": req.manual_eeg_strike,
|
| 187 |
+
"cod_date": req.cod_date,
|
| 188 |
+
},
|
| 189 |
+
)
|
| 190 |
+
|
| 191 |
+
monthly = result["monthly_revenue_df"].copy()
|
| 192 |
+
yearly = result["yearly_df"].copy()
|
| 193 |
+
|
| 194 |
+
# Ensure project_year exists (it should, from your profit.py logic)
|
| 195 |
+
if "project_year" not in monthly.columns:
|
| 196 |
+
raise ValueError("monthly_revenue_df is missing 'project_year'")
|
| 197 |
+
|
| 198 |
+
# Choose a reasonable MWh column (depends on your revenue module output)
|
| 199 |
+
mwh_col = pick_first_col(monthly, ["mwh_gross", "mwh", "mwh_delivered"])
|
| 200 |
+
if not mwh_col:
|
| 201 |
+
raise ValueError("monthly_revenue_df has none of: mwh_gross, mwh, mwh_delivered")
|
| 202 |
+
|
| 203 |
+
# Weighted average helper (for market price)
|
| 204 |
+
def wavg(group: pd.DataFrame, value_col: str, weight_col: str):
|
| 205 |
+
w = pd.to_numeric(group[weight_col], errors="coerce").fillna(0.0)
|
| 206 |
+
v = pd.to_numeric(group[value_col], errors="coerce")
|
| 207 |
+
denom = float(w.sum())
|
| 208 |
+
if denom <= 0:
|
| 209 |
+
return np.nan
|
| 210 |
+
return float((v * w).sum() / denom)
|
| 211 |
+
|
| 212 |
+
# Aggregate monthly -> yearly drivers
|
| 213 |
+
agg = (
|
| 214 |
+
monthly.groupby("project_year", as_index=False)
|
| 215 |
+
.apply(lambda g: pd.Series({
|
| 216 |
+
"mwh_gross": float(pd.to_numeric(g[mwh_col], errors="coerce").fillna(0.0).sum()),
|
| 217 |
+
"market_price_eur_per_mwh": wavg(g, "p_market", mwh_col) if "p_market" in g.columns else np.nan,
|
| 218 |
+
"cf": float(pd.to_numeric(g["cf"], errors="coerce").mean()) if "cf" in g.columns else np.nan,
|
| 219 |
+
"cr": float(pd.to_numeric(g["cr"], errors="coerce").mean()) if "cr" in g.columns else np.nan,
|
| 220 |
+
}))
|
| 221 |
+
)
|
| 222 |
+
|
| 223 |
+
# Join with yearly opex/debt/profit
|
| 224 |
+
out = yearly.merge(agg, on="project_year", how="left")
|
| 225 |
+
|
| 226 |
+
# Build the exact columns you asked for
|
| 227 |
+
table_df = pd.DataFrame({
|
| 228 |
+
"year": out["project_year"],
|
| 229 |
+
"mwh_gross": out["mwh_gross"],
|
| 230 |
+
"market_price_electricity": out["market_price_eur_per_mwh"],
|
| 231 |
+
"cf": out["cf"],
|
| 232 |
+
"cr": out["cr"],
|
| 233 |
+
"opex": out["annual_opex_eur"],
|
| 234 |
+
"debt_service": out["debt_service_eur"],
|
| 235 |
+
"profit": out["profit_after_opex_and_debt_eur"],
|
| 236 |
+
})
|
| 237 |
+
|
| 238 |
+
# Convert NaN/Inf -> None for JSON
|
| 239 |
+
table_df = table_df.replace([np.inf, -np.inf], np.nan).where(pd.notnull(table_df), None)
|
| 240 |
+
|
| 241 |
+
payload = {
|
| 242 |
+
"ok": True,
|
| 243 |
+
"npv_eur": float(result["npv_eur"]),
|
| 244 |
+
"irr": None if (float(result["irr"]) != float(result["irr"])) else float(result["irr"]),
|
| 245 |
+
"discount_rate_used": float(result["discount_rate_used"]),
|
| 246 |
+
"table": table_df.to_dict(orient="records"),
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
# Ensure strict JSON (no NaN)
|
| 250 |
+
json.dumps(payload, allow_nan=False)
|
| 251 |
+
|
| 252 |
+
return payload
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
except Exception as e:
|
| 256 |
+
raise HTTPException(status_code=400, detail=str(e))
|
app/main2.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, HTTPException
|
| 2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
from fastapi.responses import Response
|
| 4 |
+
from pydantic import BaseModel, Field
|
| 5 |
+
from typing import Optional, List
|
| 6 |
+
import pandas as pd
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
import sys
|
| 9 |
+
|
| 10 |
+
# --- Make sure Python can import from backend/model ---
|
| 11 |
+
# project/backend/app/main.py -> project/backend
|
| 12 |
+
BACKEND_ROOT = Path(__file__).resolve().parents[1]
|
| 13 |
+
MODEL_DIR = BACKEND_ROOT / "model"
|
| 14 |
+
sys.path.insert(0, str(MODEL_DIR))
|
| 15 |
+
|
| 16 |
+
# Now we can import your script
|
| 17 |
+
from profit import power_to_profit, FORECAST_MONTHS
|
| 18 |
+
|
| 19 |
+
app = FastAPI()
|
| 20 |
+
|
| 21 |
+
@app.get("/favicon.ico")
|
| 22 |
+
def favicon():
|
| 23 |
+
return Response(status_code=204)
|
| 24 |
+
|
| 25 |
+
@app.get("/")
|
| 26 |
+
def root():
|
| 27 |
+
return {"ok": True, "message": "Backend running. Go to /docs for API docs."}
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
# Allow the Vite dev server to call the API from the browser during development.
|
| 31 |
+
app.add_middleware(
|
| 32 |
+
CORSMiddleware,
|
| 33 |
+
allow_origins=["http://localhost:5173"],
|
| 34 |
+
allow_credentials=True,
|
| 35 |
+
allow_methods=["*"],
|
| 36 |
+
allow_headers=["*"],
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
# -------------------------
|
| 40 |
+
# Request/response schemas
|
| 41 |
+
# -------------------------
|
| 42 |
+
class CalcRequest(BaseModel):
|
| 43 |
+
# Settings from the UI
|
| 44 |
+
n_turbines: int = Field(ge=1)
|
| 45 |
+
hub_height_m: int = Field(ge=1)
|
| 46 |
+
turbine_type_id: int = Field(ge=0, le=2)
|
| 47 |
+
equity_eur: int = Field(ge=0)
|
| 48 |
+
|
| 49 |
+
# Revenue module required keys
|
| 50 |
+
tso_id: int = Field(ge=1)
|
| 51 |
+
eeg_on: bool
|
| 52 |
+
cod_date: str # "YYYY-MM-DD"
|
| 53 |
+
manual_eeg_strike: Optional[float] = None
|
| 54 |
+
|
| 55 |
+
# For now: constant monthly MWh (easy to wire first)
|
| 56 |
+
mwh_constant: float = Field(gt=0)
|
| 57 |
+
|
| 58 |
+
class CalcResponse(BaseModel):
|
| 59 |
+
ok: bool
|
| 60 |
+
npv_eur: float
|
| 61 |
+
irr: float
|
| 62 |
+
discount_rate_used: float
|
| 63 |
+
yearly: List[dict]
|
| 64 |
+
|
| 65 |
+
@app.post("/api/calc", response_model=CalcResponse)
|
| 66 |
+
def calc(req: CalcRequest):
|
| 67 |
+
try:
|
| 68 |
+
# Build monthly MWh series for 20 years
|
| 69 |
+
cod = pd.Timestamp(req.cod_date)
|
| 70 |
+
cod = pd.Timestamp(year=cod.year, month=cod.month, day=1)
|
| 71 |
+
|
| 72 |
+
dates = pd.date_range(cod, periods=FORECAST_MONTHS, freq="MS")
|
| 73 |
+
mwh_series = pd.Series(float(req.mwh_constant), index=dates)
|
| 74 |
+
|
| 75 |
+
result = power_to_profit(
|
| 76 |
+
mwh_monthly_20y=mwh_series,
|
| 77 |
+
turbine_type_id=req.turbine_type_id,
|
| 78 |
+
n_turbines=req.n_turbines,
|
| 79 |
+
hub_height_m=req.hub_height_m,
|
| 80 |
+
equity_eur=float(req.equity_eur),
|
| 81 |
+
revenue_kwargs={
|
| 82 |
+
"tso_id": int(req.tso_id),
|
| 83 |
+
"eeg_on": 1 if req.eeg_on else 0,
|
| 84 |
+
"manual_eeg_strike": req.manual_eeg_strike,
|
| 85 |
+
"cod_date": req.cod_date,
|
| 86 |
+
},
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
yearly_df = result["yearly_df"].copy()
|
| 90 |
+
if "year_start" in yearly_df.columns:
|
| 91 |
+
yearly_df["year_start"] = yearly_df["year_start"].astype(str)
|
| 92 |
+
|
| 93 |
+
irr_val = result["irr"]
|
| 94 |
+
irr_val = float(irr_val) if irr_val == irr_val else float("nan") # handle NaN
|
| 95 |
+
|
| 96 |
+
return {
|
| 97 |
+
"ok": True,
|
| 98 |
+
"npv_eur": float(result["npv_eur"]),
|
| 99 |
+
"irr": irr_val,
|
| 100 |
+
"discount_rate_used": float(result["discount_rate_used"]),
|
| 101 |
+
"yearly": yearly_df.to_dict(orient="records"),
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
except Exception as e:
|
| 105 |
+
raise HTTPException(status_code=400, detail=str(e))
|
entrypoint.sh
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
set -eu
|
| 3 |
+
|
| 4 |
+
DATA_ROOT="/app/inference-data"
|
| 5 |
+
ERA5_SUBDIR="ERA5_Germany"
|
| 6 |
+
ERA5_PATH="$DATA_ROOT/$ERA5_SUBDIR"
|
| 7 |
+
|
| 8 |
+
MODEL_ROOT="/app/model-artifacts"
|
| 9 |
+
|
| 10 |
+
# ------------------------------------------------------------
|
| 11 |
+
# 1) Download ERA5 dataset (only if missing/empty)
|
| 12 |
+
# Dataset: dspunituebingen/era5
|
| 13 |
+
# Folder: ERA5_Germany/**
|
| 14 |
+
# ------------------------------------------------------------
|
| 15 |
+
if [ ! -d "$ERA5_PATH" ] || [ -z "$(ls -A "$ERA5_PATH" 2>/dev/null)" ]; then
|
| 16 |
+
echo "[BOOT] Downloading dataset dspunituebingen/era5 -> $DATA_ROOT (patterns: $ERA5_SUBDIR/**)"
|
| 17 |
+
python - <<'PY'
|
| 18 |
+
import os
|
| 19 |
+
from huggingface_hub import snapshot_download
|
| 20 |
+
|
| 21 |
+
token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN")
|
| 22 |
+
|
| 23 |
+
snapshot_download(
|
| 24 |
+
repo_id="dspunituebingen/era5",
|
| 25 |
+
repo_type="dataset",
|
| 26 |
+
local_dir="/app/inference-data",
|
| 27 |
+
allow_patterns=["ERA5_Germany/**"],
|
| 28 |
+
token=token,
|
| 29 |
+
)
|
| 30 |
+
|
| 31 |
+
print("[BOOT] ERA5 data ready at /app/inference-data/ERA5_Germany")
|
| 32 |
+
PY
|
| 33 |
+
fi
|
| 34 |
+
|
| 35 |
+
# ERA5 path used by your FastAPI code via env var
|
| 36 |
+
export ERA5_DIR="$ERA5_PATH"
|
| 37 |
+
|
| 38 |
+
# ------------------------------------------------------------
|
| 39 |
+
# 2) Download model repo (only if missing/empty)
|
| 40 |
+
# Model: dspunituebingen/windproject-model
|
| 41 |
+
# Files are in the repo ROOT (final_model.pkl, feature_imputer.pkl, *.json)
|
| 42 |
+
# ------------------------------------------------------------
|
| 43 |
+
if [ ! -d "$MODEL_ROOT" ] || [ -z "$(ls -A "$MODEL_ROOT" 2>/dev/null)" ]; then
|
| 44 |
+
echo "[BOOT] Downloading model dspunituebingen/windproject-model -> $MODEL_ROOT"
|
| 45 |
+
python - <<'PY'
|
| 46 |
+
import os
|
| 47 |
+
from huggingface_hub import snapshot_download
|
| 48 |
+
|
| 49 |
+
token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN")
|
| 50 |
+
|
| 51 |
+
snapshot_download(
|
| 52 |
+
repo_id="dspunituebingen/windproject-model",
|
| 53 |
+
repo_type="model",
|
| 54 |
+
local_dir="/app/model-artifacts",
|
| 55 |
+
allow_patterns=["*.pkl", "*.json", ".gitattributes", "README.md"],
|
| 56 |
+
token=token,
|
| 57 |
+
)
|
| 58 |
+
|
| 59 |
+
print("[BOOT] Model artifacts ready at /app/model-artifacts")
|
| 60 |
+
PY
|
| 61 |
+
fi
|
| 62 |
+
|
| 63 |
+
# Model directory used by your FastAPI code via env var
|
| 64 |
+
# (Your model files are directly in the repo root, so MODEL_DIR == MODEL_ROOT)
|
| 65 |
+
export MODEL_DIR="$MODEL_ROOT"
|
| 66 |
+
|
| 67 |
+
# ------------------------------------------------------------
|
| 68 |
+
# 3) Turbine curves path (try dataset first, then repo fallbacks)
|
| 69 |
+
# ------------------------------------------------------------
|
| 70 |
+
if [ -z "${TURBINE_CURVES:-}" ] && [ -f "$DATA_ROOT/turbine_power_curves.json" ]; then
|
| 71 |
+
export TURBINE_CURVES="$DATA_ROOT/turbine_power_curves.json"
|
| 72 |
+
fi
|
| 73 |
+
|
| 74 |
+
if [ -z "${TURBINE_CURVES:-}" ]; then
|
| 75 |
+
if [ -f "/app/wind-power-climate-ml/data/turbine_power_curves.json" ]; then
|
| 76 |
+
export TURBINE_CURVES="/app/wind-power-climate-ml/data/turbine_power_curves.json"
|
| 77 |
+
elif [ -f "/app/wind-power-climate-ml/Data/turbine_power_curves.json" ]; then
|
| 78 |
+
export TURBINE_CURVES="/app/wind-power-climate-ml/Data/turbine_power_curves.json"
|
| 79 |
+
fi
|
| 80 |
+
fi
|
| 81 |
+
|
| 82 |
+
# ------------------------------------------------------------
|
| 83 |
+
# 4) Debug / sanity checks
|
| 84 |
+
# ------------------------------------------------------------
|
| 85 |
+
echo "[CONFIG] ERA5_DIR=$ERA5_DIR"
|
| 86 |
+
echo "[CONFIG] MODEL_DIR=$MODEL_DIR"
|
| 87 |
+
echo "[CONFIG] TURBINE_CURVES=${TURBINE_CURVES:-<default in code>}"
|
| 88 |
+
|
| 89 |
+
echo "[CHECK] ERA5_DIR listing:"
|
| 90 |
+
ls -lah "$ERA5_DIR" | head -n 50 || true
|
| 91 |
+
|
| 92 |
+
echo "[CHECK] MODEL_DIR listing:"
|
| 93 |
+
ls -lah "$MODEL_DIR" | head -n 50 || true
|
| 94 |
+
|
| 95 |
+
if [ -n "${TURBINE_CURVES:-}" ]; then
|
| 96 |
+
echo "[CHECK] TURBINE_CURVES exists:"
|
| 97 |
+
ls -lah "$TURBINE_CURVES" || true
|
| 98 |
+
fi
|
| 99 |
+
|
| 100 |
+
# ------------------------------------------------------------
|
| 101 |
+
# 5) Start FastAPI (Uvicorn)
|
| 102 |
+
# ------------------------------------------------------------
|
| 103 |
+
cd /app/wind-power-climate-ml
|
| 104 |
+
exec python -m uvicorn website.api:app --app-dir src --host 0.0.0.0 --port 7860 --log-level info
|
model/costs/capex/capex.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
from dataclasses import dataclass
|
| 3 |
+
|
| 4 |
+
# -----------------------
|
| 5 |
+
# Turbine archetypes
|
| 6 |
+
# -----------------------
|
| 7 |
+
@dataclass(frozen=True)
|
| 8 |
+
class TurbineType:
|
| 9 |
+
name: str
|
| 10 |
+
p_mw: float
|
| 11 |
+
rotor_diameter_m: float
|
| 12 |
+
|
| 13 |
+
TURBINE_TYPES = {
|
| 14 |
+
"LOW_WIND": TurbineType("LOW_WIND", 6.0, 170.0),
|
| 15 |
+
"BALANCED": TurbineType("BALANCED", 5.6, 160.0),
|
| 16 |
+
"HIGH_WIND": TurbineType("HIGH_WIND", 4.2, 130.0),
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
# -----------------------
|
| 20 |
+
# BoP costs (2025–2028)
|
| 21 |
+
# -----------------------
|
| 22 |
+
BOP_EUR_PER_KW = 551 # foundations, grid, roads, planning, etc.
|
| 23 |
+
|
| 24 |
+
# -----------------------
|
| 25 |
+
# Engineering functions
|
| 26 |
+
# -----------------------
|
| 27 |
+
def sfl_w_per_m2(p_mw, rotor_diameter_m):
|
| 28 |
+
area = math.pi * (rotor_diameter_m / 2) ** 2
|
| 29 |
+
return (p_mw * 1_000_000) / area
|
| 30 |
+
|
| 31 |
+
def hik_eur_per_kw(p_mw, sfl, hub_height_m):
|
| 32 |
+
"""
|
| 33 |
+
HIK regression from German industry data:
|
| 34 |
+
HIK = 1476.19 - 65.62*P - 1.29*SFL + 3.50*NH
|
| 35 |
+
"""
|
| 36 |
+
return 1476.19 - 65.62 * p_mw - 1.29 * sfl + 3.50 * hub_height_m
|
| 37 |
+
|
| 38 |
+
# -----------------------
|
| 39 |
+
# Wind park CAPEX
|
| 40 |
+
# -----------------------
|
| 41 |
+
def windpark_capex(n_turbines, turbine_type_key, hub_height_m):
|
| 42 |
+
t = TURBINE_TYPES[turbine_type_key]
|
| 43 |
+
|
| 44 |
+
park_mw = n_turbines * t.p_mw
|
| 45 |
+
sfl = sfl_w_per_m2(t.p_mw, t.rotor_diameter_m)
|
| 46 |
+
|
| 47 |
+
turbine_capex_kw = hik_eur_per_kw(t.p_mw, sfl, hub_height_m)
|
| 48 |
+
total_capex_kw = turbine_capex_kw + BOP_EUR_PER_KW
|
| 49 |
+
|
| 50 |
+
total_capex = park_mw * 1000 * total_capex_kw
|
| 51 |
+
|
| 52 |
+
return {
|
| 53 |
+
"park_mw": park_mw,
|
| 54 |
+
"sfl": sfl,
|
| 55 |
+
"turbine_capex_eur_per_kw": turbine_capex_kw,
|
| 56 |
+
"bop_eur_per_kw": BOP_EUR_PER_KW,
|
| 57 |
+
"total_capex_eur_per_kw": total_capex_kw,
|
| 58 |
+
"total_capex_eur": total_capex
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
# -----------------------
|
| 62 |
+
# Pretty printer
|
| 63 |
+
# -----------------------
|
| 64 |
+
def print_windpark_result(n_turbines, turbine_type, hub_height_m):
|
| 65 |
+
res = windpark_capex(n_turbines, turbine_type, hub_height_m)
|
| 66 |
+
t = TURBINE_TYPES[turbine_type]
|
| 67 |
+
|
| 68 |
+
print(
|
| 69 |
+
f"{turbine_type} ({n_turbines} × {t.p_mw} MW) | "
|
| 70 |
+
f"NH={hub_height_m} m | "
|
| 71 |
+
f"SFL={res['sfl']:.0f} W/m² | "
|
| 72 |
+
f"Turbine={res['turbine_capex_eur_per_kw']:.0f} €/kW | "
|
| 73 |
+
f"BoP={res['bop_eur_per_kw']:.0f} €/kW | "
|
| 74 |
+
f"Total={res['total_capex_eur_per_kw']:.0f} €/kW | "
|
| 75 |
+
f"CAPEX={res['total_capex_eur']/1e6:.1f} M€"
|
| 76 |
+
)
|
| 77 |
+
|
| 78 |
+
# -----------------------
|
| 79 |
+
# Example
|
| 80 |
+
# -----------------------
|
| 81 |
+
if __name__ == "__main__":
|
| 82 |
+
print_windpark_result(12, "BALANCED", 160)
|
| 83 |
+
print_windpark_result(15, "HIGH_WIND", 120)
|
| 84 |
+
print_windpark_result(10, "LOW_WIND", 180)
|
model/costs/capex/capex_mod.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# capex.py
|
| 2 |
+
#
|
| 3 |
+
# Central callable CAPEX module for power_to_profit.py
|
| 4 |
+
# - Accepts turbine type as an INDEX (0,1,2) coming from profit.py
|
| 5 |
+
# - Accepts number of turbines and hub height
|
| 6 |
+
# - Returns a dict including keys used by power_to_profit.py:
|
| 7 |
+
# - park_mw
|
| 8 |
+
# - total_capex_eur
|
| 9 |
+
#
|
| 10 |
+
# Mapping (you can change ordering if you prefer):
|
| 11 |
+
# 0 -> LOW_WIND
|
| 12 |
+
# 1 -> BALANCED
|
| 13 |
+
# 2 -> HIGH_WIND
|
| 14 |
+
|
| 15 |
+
import math
|
| 16 |
+
from dataclasses import dataclass
|
| 17 |
+
from typing import Dict, Any
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
# -----------------------
|
| 21 |
+
# Turbine archetypes
|
| 22 |
+
# -----------------------
|
| 23 |
+
@dataclass(frozen=True)
|
| 24 |
+
class TurbineType:
|
| 25 |
+
name: str
|
| 26 |
+
p_mw: float
|
| 27 |
+
rotor_diameter_m: float
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
TURBINE_TYPES_BY_KEY: Dict[str, TurbineType] = {
|
| 31 |
+
"LOW_WIND": TurbineType("LOW_WIND", 6.0, 170.0),
|
| 32 |
+
"BALANCED": TurbineType("BALANCED", 5.6, 160.0),
|
| 33 |
+
"HIGH_WIND": TurbineType("HIGH_WIND", 4.2, 130.0),
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
# Index mapping expected by profit.py
|
| 37 |
+
TURBINE_TYPE_INDEX_MAP: Dict[int, str] = {
|
| 38 |
+
0: "LOW_WIND",
|
| 39 |
+
1: "BALANCED",
|
| 40 |
+
2: "HIGH_WIND",
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
# -----------------------
|
| 44 |
+
# BoP costs (2025–2028)
|
| 45 |
+
# -----------------------
|
| 46 |
+
BOP_EUR_PER_KW = 551.0 # foundations, grid, roads, planning, etc.
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
# -----------------------
|
| 50 |
+
# Engineering functions
|
| 51 |
+
# -----------------------
|
| 52 |
+
def sfl_w_per_m2(p_mw: float, rotor_diameter_m: float) -> float:
|
| 53 |
+
"""Specific rated power density (W/m²) based on rotor swept area."""
|
| 54 |
+
area = math.pi * (rotor_diameter_m / 2.0) ** 2
|
| 55 |
+
return (p_mw * 1_000_000.0) / area
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def hik_eur_per_kw(p_mw: float, sfl: float, hub_height_m: float) -> float:
|
| 59 |
+
"""
|
| 60 |
+
HIK regression from German industry data:
|
| 61 |
+
HIK = 1476.19 - 65.62*P - 1.29*SFL + 3.50*NH
|
| 62 |
+
"""
|
| 63 |
+
return 1476.19 - 65.62 * p_mw - 1.29 * sfl + 3.50 * hub_height_m
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
# -----------------------
|
| 67 |
+
# Public API used by power_to_profit.py
|
| 68 |
+
# -----------------------
|
| 69 |
+
def windpark_capex(
|
| 70 |
+
*,
|
| 71 |
+
n_turbines: int,
|
| 72 |
+
turbine_type_id: int,
|
| 73 |
+
hub_height_m: float,
|
| 74 |
+
) -> Dict[str, Any]:
|
| 75 |
+
"""
|
| 76 |
+
Compute wind park CAPEX based on turbine archetype + hub height.
|
| 77 |
+
|
| 78 |
+
Parameters
|
| 79 |
+
----------
|
| 80 |
+
n_turbines : int
|
| 81 |
+
Number of turbines in the park.
|
| 82 |
+
turbine_type_id : int
|
| 83 |
+
Turbine type index coming from profit.py:
|
| 84 |
+
0 -> LOW_WIND
|
| 85 |
+
1 -> BALANCED
|
| 86 |
+
2 -> HIGH_WIND
|
| 87 |
+
hub_height_m : float
|
| 88 |
+
Hub height in meters.
|
| 89 |
+
|
| 90 |
+
Returns
|
| 91 |
+
-------
|
| 92 |
+
dict including:
|
| 93 |
+
- park_mw
|
| 94 |
+
- total_capex_eur
|
| 95 |
+
plus breakdown fields.
|
| 96 |
+
"""
|
| 97 |
+
if not isinstance(n_turbines, int) or n_turbines <= 0:
|
| 98 |
+
raise ValueError("n_turbines must be a positive integer.")
|
| 99 |
+
|
| 100 |
+
try:
|
| 101 |
+
turbine_type_id = int(turbine_type_id)
|
| 102 |
+
except Exception as e:
|
| 103 |
+
raise ValueError("turbine_type_id must be an integer (0,1,2).") from e
|
| 104 |
+
|
| 105 |
+
if turbine_type_id not in TURBINE_TYPE_INDEX_MAP:
|
| 106 |
+
raise ValueError(
|
| 107 |
+
f"Unknown turbine_type_id={turbine_type_id}. "
|
| 108 |
+
f"Valid: {sorted(TURBINE_TYPE_INDEX_MAP.keys())} "
|
| 109 |
+
f"(0=LOW_WIND, 1=BALANCED, 2=HIGH_WIND)"
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
hub_height_m = float(hub_height_m)
|
| 113 |
+
if hub_height_m <= 0:
|
| 114 |
+
raise ValueError("hub_height_m must be > 0.")
|
| 115 |
+
|
| 116 |
+
turbine_key = TURBINE_TYPE_INDEX_MAP[turbine_type_id]
|
| 117 |
+
t = TURBINE_TYPES_BY_KEY[turbine_key]
|
| 118 |
+
|
| 119 |
+
park_mw = float(n_turbines) * float(t.p_mw)
|
| 120 |
+
sfl = sfl_w_per_m2(t.p_mw, t.rotor_diameter_m)
|
| 121 |
+
|
| 122 |
+
turbine_capex_eur_per_kw = hik_eur_per_kw(t.p_mw, sfl, hub_height_m)
|
| 123 |
+
total_capex_eur_per_kw = float(turbine_capex_eur_per_kw) + float(BOP_EUR_PER_KW)
|
| 124 |
+
|
| 125 |
+
total_capex_eur = park_mw * 1000.0 * total_capex_eur_per_kw
|
| 126 |
+
|
| 127 |
+
return {
|
| 128 |
+
"turbine_type_id": int(turbine_type_id),
|
| 129 |
+
"turbine_type": t.name,
|
| 130 |
+
"n_turbines": int(n_turbines),
|
| 131 |
+
"hub_height_m": float(hub_height_m),
|
| 132 |
+
"park_mw": float(park_mw),
|
| 133 |
+
"rotor_diameter_m": float(t.rotor_diameter_m),
|
| 134 |
+
"sfl": float(sfl),
|
| 135 |
+
"turbine_capex_eur_per_kw": float(turbine_capex_eur_per_kw),
|
| 136 |
+
"bop_eur_per_kw": float(BOP_EUR_PER_KW),
|
| 137 |
+
"total_capex_eur_per_kw": float(total_capex_eur_per_kw),
|
| 138 |
+
"total_capex_eur": float(total_capex_eur),
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
# -----------------------
|
| 143 |
+
# Convenience helper (optional)
|
| 144 |
+
# -----------------------
|
| 145 |
+
def print_windpark_result(n_turbines: int, turbine_type_id: int, hub_height_m: float) -> None:
|
| 146 |
+
res = windpark_capex(
|
| 147 |
+
n_turbines=n_turbines,
|
| 148 |
+
turbine_type_id=turbine_type_id,
|
| 149 |
+
hub_height_m=hub_height_m,
|
| 150 |
+
)
|
| 151 |
+
print(
|
| 152 |
+
f"Type={res['turbine_type']} (id={res['turbine_type_id']}) | "
|
| 153 |
+
f"{res['n_turbines']} × {TURBINE_TYPES_BY_KEY[res['turbine_type']].p_mw} MW | "
|
| 154 |
+
f"NH={res['hub_height_m']:.0f} m | "
|
| 155 |
+
f"SFL={res['sfl']:.0f} W/m² | "
|
| 156 |
+
f"Turbine={res['turbine_capex_eur_per_kw']:.0f} €/kW | "
|
| 157 |
+
f"BoP={res['bop_eur_per_kw']:.0f} €/kW | "
|
| 158 |
+
f"Total={res['total_capex_eur_per_kw']:.0f} €/kW | "
|
| 159 |
+
f"CAPEX={res['total_capex_eur']/1e6:.1f} M€"
|
| 160 |
+
)
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
# -----------------------
|
| 164 |
+
# Example
|
| 165 |
+
# -----------------------
|
| 166 |
+
if __name__ == "__main__":
|
| 167 |
+
print_windpark_result(12, 1, 160) # BALANCED
|
| 168 |
+
print_windpark_result(15, 2, 120) # HIGH_WIND
|
| 169 |
+
print_windpark_result(10, 0, 180) # LOW_WIND
|
model/costs/capex/other_costs.csv
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
category,eur_per_kw,share
|
| 2 |
+
Planning_and_development,163,0.30
|
| 3 |
+
Grid_connection,133,0.24
|
| 4 |
+
Infrastructure_and_foundations,119,0.22
|
| 5 |
+
Compensation,35,0.06
|
| 6 |
+
Other,101,0.18
|
| 7 |
+
Total,551,1.00
|
model/costs/finance/finance.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
def financing_model(
|
| 4 |
+
capex_eur,
|
| 5 |
+
equity_share=0.15,
|
| 6 |
+
debt_rate=0.045,
|
| 7 |
+
equity_return=0.08,
|
| 8 |
+
debt_tenor_years=20
|
| 9 |
+
):
|
| 10 |
+
"""
|
| 11 |
+
Simple project finance model for a wind park.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
debt_share = 1 - equity_share
|
| 15 |
+
|
| 16 |
+
equity = capex_eur * equity_share
|
| 17 |
+
debt = capex_eur * debt_share
|
| 18 |
+
|
| 19 |
+
# annuity loan formula
|
| 20 |
+
r = debt_rate
|
| 21 |
+
n = debt_tenor_years
|
| 22 |
+
annuity_factor = r * (1 + r)**n / ((1 + r)**n - 1)
|
| 23 |
+
annual_debt_service = debt * annuity_factor
|
| 24 |
+
|
| 25 |
+
# total debt repaid
|
| 26 |
+
total_debt_repayment = annual_debt_service * n
|
| 27 |
+
total_interest = total_debt_repayment - debt
|
| 28 |
+
|
| 29 |
+
# Weighted Average Cost of Capital
|
| 30 |
+
wacc = equity_share * equity_return + debt_share * debt_rate
|
| 31 |
+
|
| 32 |
+
return {
|
| 33 |
+
"capex_eur": capex_eur,
|
| 34 |
+
"equity_share": equity_share,
|
| 35 |
+
"debt_share": debt_share,
|
| 36 |
+
"equity_eur": equity,
|
| 37 |
+
"debt_eur": debt,
|
| 38 |
+
"annual_debt_service_eur": annual_debt_service,
|
| 39 |
+
"total_interest_paid_eur": total_interest,
|
| 40 |
+
"wacc": wacc
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
# -------------------------------
|
| 44 |
+
# Realistic German wind park example
|
| 45 |
+
# -------------------------------
|
| 46 |
+
if __name__ == "__main__":
|
| 47 |
+
capex = 80_000_000 # 80 million € project
|
| 48 |
+
equity_share = 0.15 # 15% equity (aggressive but bankable)
|
| 49 |
+
debt_rate = 0.045 # 4.5% KfW-270 loan
|
| 50 |
+
equity_return = 0.085 # 8.5% equity target
|
| 51 |
+
tenor = 18 # 18-year loan
|
| 52 |
+
|
| 53 |
+
result = financing_model(
|
| 54 |
+
capex_eur=capex,
|
| 55 |
+
equity_share=equity_share,
|
| 56 |
+
debt_rate=debt_rate,
|
| 57 |
+
equity_return=equity_return,
|
| 58 |
+
debt_tenor_years=tenor
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
print("---- German Onshore Wind Financing ----")
|
| 62 |
+
print(f"CAPEX: {result['capex_eur']/1e6:.1f} M€")
|
| 63 |
+
print(f"Equity (15%): {result['equity_eur']/1e6:.1f} M€")
|
| 64 |
+
print(f"Debt (85%): {result['debt_eur']/1e6:.1f} M€")
|
| 65 |
+
print(f"Annual debt svc: {result['annual_debt_service_eur']/1e6:.2f} M€ / year")
|
| 66 |
+
print(f"Total interest: {result['total_interest_paid_eur']/1e6:.1f} M€ over {tenor} years")
|
| 67 |
+
print(f"WACC: {result['wacc']*100:.2f} %")
|
model/costs/finance/finance_mod.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# finance.py
|
| 2 |
+
#
|
| 3 |
+
# Central callable finance module for power_to_profit.py
|
| 4 |
+
# - Inputs come from profit.py:
|
| 5 |
+
# - capex_eur (from capex_res["total_capex_eur"])
|
| 6 |
+
# - equity_eur (absolute € amount; we compute equity_share)
|
| 7 |
+
# - debt_rate, equity_return, debt_tenor_years
|
| 8 |
+
# - forecast_months (project horizon; default 240)
|
| 9 |
+
# - Outputs include:
|
| 10 |
+
# - equity_share_derived
|
| 11 |
+
# - annual_debt_service_eur
|
| 12 |
+
# - debt_service_yearly_df (project_year schedule aligned to horizon)
|
| 13 |
+
# - wacc
|
| 14 |
+
#
|
| 15 |
+
# Notes:
|
| 16 |
+
# - We keep the debt service as an ANNUITY yearly payment (like your current model).
|
| 17 |
+
# - Horizon alignment: we build project_year 1..ceil(forecast_months/12) and set payments
|
| 18 |
+
# to 0 after debt_tenor_years.
|
| 19 |
+
|
| 20 |
+
import math
|
| 21 |
+
import pandas as pd
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def financing_model(
|
| 25 |
+
*,
|
| 26 |
+
capex_eur: float,
|
| 27 |
+
equity_eur: float | None = None,
|
| 28 |
+
# If equity_eur is None, you can still pass equity_share directly
|
| 29 |
+
equity_share: float | None = None,
|
| 30 |
+
debt_rate: float = 0.045,
|
| 31 |
+
equity_return: float = 0.08,
|
| 32 |
+
debt_tenor_years: int = 20,
|
| 33 |
+
forecast_months: int = 240,
|
| 34 |
+
) -> dict:
|
| 35 |
+
"""
|
| 36 |
+
Simple project finance model for a wind park.
|
| 37 |
+
|
| 38 |
+
Parameters
|
| 39 |
+
----------
|
| 40 |
+
capex_eur : float
|
| 41 |
+
Total project CAPEX in €.
|
| 42 |
+
equity_eur : float | None
|
| 43 |
+
Absolute equity amount in €. If provided, equity_share is derived as equity_eur/capex_eur.
|
| 44 |
+
equity_share : float | None
|
| 45 |
+
Optional direct equity share (0..1). Used only if equity_eur is None.
|
| 46 |
+
debt_rate : float
|
| 47 |
+
Annual debt interest rate (e.g., 0.045).
|
| 48 |
+
equity_return : float
|
| 49 |
+
Annual equity target return (used for WACC).
|
| 50 |
+
debt_tenor_years : int
|
| 51 |
+
Loan tenor in years (annuity payments).
|
| 52 |
+
forecast_months : int
|
| 53 |
+
Project horizon in months (default 240 = 20y). Used to create aligned debt schedule.
|
| 54 |
+
|
| 55 |
+
Returns
|
| 56 |
+
-------
|
| 57 |
+
dict with keys used by power_to_profit.py plus schedule:
|
| 58 |
+
- annual_debt_service_eur
|
| 59 |
+
- wacc
|
| 60 |
+
- equity_share_derived
|
| 61 |
+
- debt_service_yearly_df (project_year, debt_service_eur)
|
| 62 |
+
- plus breakdown fields (equity_eur, debt_eur, total_interest_paid_eur, etc.)
|
| 63 |
+
"""
|
| 64 |
+
|
| 65 |
+
capex_eur = float(capex_eur)
|
| 66 |
+
if capex_eur <= 0:
|
| 67 |
+
raise ValueError("capex_eur must be > 0")
|
| 68 |
+
|
| 69 |
+
forecast_months = int(forecast_months)
|
| 70 |
+
if forecast_months <= 0:
|
| 71 |
+
raise ValueError("forecast_months must be > 0")
|
| 72 |
+
|
| 73 |
+
debt_rate = float(debt_rate)
|
| 74 |
+
if debt_rate < 0:
|
| 75 |
+
raise ValueError("debt_rate must be >= 0")
|
| 76 |
+
|
| 77 |
+
equity_return = float(equity_return)
|
| 78 |
+
|
| 79 |
+
debt_tenor_years = int(debt_tenor_years)
|
| 80 |
+
if debt_tenor_years <= 0:
|
| 81 |
+
raise ValueError("debt_tenor_years must be > 0")
|
| 82 |
+
|
| 83 |
+
# -----------------------
|
| 84 |
+
# Derive equity share
|
| 85 |
+
# -----------------------
|
| 86 |
+
if equity_eur is not None:
|
| 87 |
+
equity_eur = float(equity_eur)
|
| 88 |
+
if equity_eur < 0:
|
| 89 |
+
raise ValueError("equity_eur must be >= 0")
|
| 90 |
+
equity_share_derived = equity_eur / capex_eur
|
| 91 |
+
else:
|
| 92 |
+
if equity_share is None:
|
| 93 |
+
# default: 15% equity if nothing provided
|
| 94 |
+
equity_share_derived = 0.15
|
| 95 |
+
else:
|
| 96 |
+
equity_share_derived = float(equity_share)
|
| 97 |
+
|
| 98 |
+
# clamp to [0, 1)
|
| 99 |
+
equity_share_derived = max(0.0, min(equity_share_derived, 0.999999))
|
| 100 |
+
|
| 101 |
+
debt_share = 1.0 - equity_share_derived
|
| 102 |
+
|
| 103 |
+
equity_eur_final = capex_eur * equity_share_derived
|
| 104 |
+
debt_eur = capex_eur * debt_share
|
| 105 |
+
|
| 106 |
+
# -----------------------
|
| 107 |
+
# Annuity debt service (annual)
|
| 108 |
+
# -----------------------
|
| 109 |
+
r = debt_rate
|
| 110 |
+
n = debt_tenor_years
|
| 111 |
+
|
| 112 |
+
if debt_eur <= 0:
|
| 113 |
+
annual_debt_service_eur = 0.0
|
| 114 |
+
total_interest_paid_eur = 0.0
|
| 115 |
+
else:
|
| 116 |
+
if r == 0.0:
|
| 117 |
+
annual_debt_service_eur = debt_eur / n
|
| 118 |
+
else:
|
| 119 |
+
annuity_factor = r * (1.0 + r) ** n / ((1.0 + r) ** n - 1.0)
|
| 120 |
+
annual_debt_service_eur = debt_eur * annuity_factor
|
| 121 |
+
|
| 122 |
+
total_debt_repayment = annual_debt_service_eur * n
|
| 123 |
+
total_interest_paid_eur = total_debt_repayment - debt_eur
|
| 124 |
+
|
| 125 |
+
# -----------------------
|
| 126 |
+
# WACC (simple weighted blend)
|
| 127 |
+
# -----------------------
|
| 128 |
+
wacc = equity_share_derived * equity_return + debt_share * debt_rate
|
| 129 |
+
|
| 130 |
+
# -----------------------
|
| 131 |
+
# Build aligned debt schedule by project year
|
| 132 |
+
# -----------------------
|
| 133 |
+
horizon_years = int(math.ceil(forecast_months / 12.0))
|
| 134 |
+
years = list(range(1, horizon_years + 1))
|
| 135 |
+
|
| 136 |
+
debt_service = [
|
| 137 |
+
float(annual_debt_service_eur) if y <= debt_tenor_years else 0.0
|
| 138 |
+
for y in years
|
| 139 |
+
]
|
| 140 |
+
|
| 141 |
+
debt_service_yearly_df = pd.DataFrame({
|
| 142 |
+
"project_year": years,
|
| 143 |
+
"debt_service_eur": debt_service,
|
| 144 |
+
})
|
| 145 |
+
|
| 146 |
+
return {
|
| 147 |
+
"capex_eur": float(capex_eur),
|
| 148 |
+
"equity_share_derived": float(equity_share_derived),
|
| 149 |
+
"debt_share": float(debt_share),
|
| 150 |
+
"equity_eur": float(equity_eur_final),
|
| 151 |
+
"debt_eur": float(debt_eur),
|
| 152 |
+
"debt_rate": float(debt_rate),
|
| 153 |
+
"equity_return": float(equity_return),
|
| 154 |
+
"debt_tenor_years": int(debt_tenor_years),
|
| 155 |
+
"annual_debt_service_eur": float(annual_debt_service_eur),
|
| 156 |
+
"total_interest_paid_eur": float(total_interest_paid_eur),
|
| 157 |
+
"wacc": float(wacc),
|
| 158 |
+
"forecast_months": int(forecast_months),
|
| 159 |
+
"horizon_years": int(horizon_years),
|
| 160 |
+
"debt_service_yearly_df": debt_service_yearly_df,
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
# -------------------------------
|
| 165 |
+
# Standalone test / example
|
| 166 |
+
# -------------------------------
|
| 167 |
+
if __name__ == "__main__":
|
| 168 |
+
capex = 80_000_000
|
| 169 |
+
equity_eur = 12_000_000
|
| 170 |
+
debt_rate = 0.045
|
| 171 |
+
equity_return = 0.085
|
| 172 |
+
tenor = 18
|
| 173 |
+
forecast_months = 240
|
| 174 |
+
|
| 175 |
+
result = financing_model(
|
| 176 |
+
capex_eur=capex,
|
| 177 |
+
equity_eur=equity_eur,
|
| 178 |
+
debt_rate=debt_rate,
|
| 179 |
+
equity_return=equity_return,
|
| 180 |
+
debt_tenor_years=tenor,
|
| 181 |
+
forecast_months=forecast_months,
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
print("---- German Onshore Wind Financing ----")
|
| 185 |
+
print(f"CAPEX: {result['capex_eur']/1e6:.1f} M€")
|
| 186 |
+
print(f"Equity (input): {equity_eur/1e6:.1f} M€")
|
| 187 |
+
print(f"Equity share: {result['equity_share_derived']*100:.1f} %")
|
| 188 |
+
print(f"Debt: {result['debt_eur']/1e6:.1f} M€")
|
| 189 |
+
print(f"Annual debt service: {result['annual_debt_service_eur']/1e6:.2f} M€ / year")
|
| 190 |
+
print(f"Total interest: {result['total_interest_paid_eur']/1e6:.1f} M€ over {tenor} years")
|
| 191 |
+
print(f"WACC: {result['wacc']*100:.2f} %")
|
| 192 |
+
print(result["debt_service_yearly_df"].head())
|
model/costs/opex/opex.csv
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
decade,maintenance,lease,operations,insurance,marketing,decommissioning,other,total_eur_per_kw_year
|
| 2 |
+
1,15,19,5,4,1,3,6,53
|
| 3 |
+
2,14,20,5,4,1,3,6,55
|
model/costs/opex/opex.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
|
| 3 |
+
OPEX_DECADE_1 = 53 # €/kW/year (years 1–10)
|
| 4 |
+
OPEX_DECADE_2 = 55 # €/kW/year (years 11–20)
|
| 5 |
+
|
| 6 |
+
def windpark_opex_timeseries(park_mw, years=20):
|
| 7 |
+
"""
|
| 8 |
+
Returns a DataFrame with yearly O&M costs and total lifetime OPEX.
|
| 9 |
+
"""
|
| 10 |
+
park_kw = park_mw * 1000
|
| 11 |
+
data = []
|
| 12 |
+
|
| 13 |
+
for year in range(1, years + 1):
|
| 14 |
+
if year <= 10:
|
| 15 |
+
opex_per_kw = OPEX_DECADE_1
|
| 16 |
+
else:
|
| 17 |
+
opex_per_kw = OPEX_DECADE_2
|
| 18 |
+
|
| 19 |
+
annual_cost = park_kw * opex_per_kw
|
| 20 |
+
|
| 21 |
+
data.append({
|
| 22 |
+
"year": year,
|
| 23 |
+
"opex_eur_per_kw": opex_per_kw,
|
| 24 |
+
"annual_opex_eur": annual_cost
|
| 25 |
+
})
|
| 26 |
+
|
| 27 |
+
df = pd.DataFrame(data)
|
| 28 |
+
total = df["annual_opex_eur"].sum()
|
| 29 |
+
|
| 30 |
+
return df, total
|
| 31 |
+
|
| 32 |
+
df, total = windpark_opex_timeseries(park_mw=50)
|
| 33 |
+
|
| 34 |
+
print(df)
|
| 35 |
+
print("Total OPEX over 20 years:", total/1e6, "million €")
|
model/costs/opex/opex_mod.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# opex.py
|
| 2 |
+
#
|
| 3 |
+
# Central callable OPEX module for power_to_profit.py
|
| 4 |
+
# - Inputs come from profit.py:
|
| 5 |
+
# - park_mw (already computed from capex_res["park_mw"])
|
| 6 |
+
# - forecast_months (typically 240 for 20 years)
|
| 7 |
+
# - Produces monthly + project-year OPEX aligned to the same 12-month blocks as revenue.
|
| 8 |
+
|
| 9 |
+
import pandas as pd
|
| 10 |
+
|
| 11 |
+
# €/kW/year (real terms)
|
| 12 |
+
OPEX_DECADE_1 = 53.0 # years 1–10
|
| 13 |
+
OPEX_DECADE_2 = 55.0 # years 11–20
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def windpark_opex_timeseries(
|
| 17 |
+
*,
|
| 18 |
+
park_mw: float,
|
| 19 |
+
forecast_months: int = 240,
|
| 20 |
+
) -> tuple[pd.DataFrame, float]:
|
| 21 |
+
"""
|
| 22 |
+
Compute OPEX time series aligned to project months/years.
|
| 23 |
+
|
| 24 |
+
Parameters
|
| 25 |
+
----------
|
| 26 |
+
park_mw : float
|
| 27 |
+
Park capacity in MW.
|
| 28 |
+
forecast_months : int
|
| 29 |
+
Number of months in horizon (default 240 = 20y).
|
| 30 |
+
|
| 31 |
+
Returns
|
| 32 |
+
-------
|
| 33 |
+
yearly_df : DataFrame with columns:
|
| 34 |
+
- project_year (1..ceil(forecast_months/12))
|
| 35 |
+
- annual_opex_eur
|
| 36 |
+
- opex_eur_per_kw_year (rate applied for that project year)
|
| 37 |
+
total_opex_eur : float
|
| 38 |
+
Total OPEX over the horizon (sum of monthly, equivalently yearly).
|
| 39 |
+
"""
|
| 40 |
+
park_mw = float(park_mw)
|
| 41 |
+
if park_mw <= 0:
|
| 42 |
+
raise ValueError("park_mw must be > 0")
|
| 43 |
+
|
| 44 |
+
forecast_months = int(forecast_months)
|
| 45 |
+
if forecast_months <= 0:
|
| 46 |
+
raise ValueError("forecast_months must be > 0")
|
| 47 |
+
|
| 48 |
+
park_kw = park_mw * 1000.0
|
| 49 |
+
|
| 50 |
+
# Build monthly series (project month 1..N)
|
| 51 |
+
m = pd.DataFrame({"project_month": range(1, forecast_months + 1)})
|
| 52 |
+
m["project_year"] = ((m["project_month"] - 1) // 12) + 1 # 1..20 (for 240)
|
| 53 |
+
|
| 54 |
+
# Choose rate per project year (decade 1 vs decade 2)
|
| 55 |
+
m["opex_eur_per_kw_year"] = m["project_year"].apply(
|
| 56 |
+
lambda y: OPEX_DECADE_1 if y <= 10 else OPEX_DECADE_2
|
| 57 |
+
).astype(float)
|
| 58 |
+
|
| 59 |
+
# Convert annual €/kW/year into monthly €:
|
| 60 |
+
# monthly_cost = park_kw * (€/kW/year) / 12
|
| 61 |
+
m["monthly_opex_eur"] = park_kw * m["opex_eur_per_kw_year"] / 12.0
|
| 62 |
+
|
| 63 |
+
total_opex_eur = float(m["monthly_opex_eur"].sum())
|
| 64 |
+
|
| 65 |
+
# Aggregate to project-year (sum of months in that year; last year might be partial if forecast_months not multiple of 12)
|
| 66 |
+
yearly_df = (
|
| 67 |
+
m.groupby("project_year", as_index=False)
|
| 68 |
+
.agg(
|
| 69 |
+
annual_opex_eur=("monthly_opex_eur", "sum"),
|
| 70 |
+
opex_eur_per_kw_year=("opex_eur_per_kw_year", "first"),
|
| 71 |
+
months_in_year=("monthly_opex_eur", "size"),
|
| 72 |
+
)
|
| 73 |
+
.sort_values("project_year")
|
| 74 |
+
.reset_index(drop=True)
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
return yearly_df, total_opex_eur
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
# -----------------------
|
| 81 |
+
# Optional standalone test
|
| 82 |
+
# -----------------------
|
| 83 |
+
if __name__ == "__main__":
|
| 84 |
+
yearly, total = windpark_opex_timeseries(park_mw=50, forecast_months=240)
|
| 85 |
+
print(yearly.head(12))
|
| 86 |
+
print("Total OPEX:", total / 1e6, "million €")
|
model/costs/planning/merge.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
|
| 3 |
+
# Load the three Bundesland tables
|
| 4 |
+
planning = pd.read_csv("planning_phase_bundesland.csv")
|
| 5 |
+
permitting = pd.read_csv("permitting_phase_bundesland.csv")
|
| 6 |
+
total = pd.read_csv("total_bundesland.csv")
|
| 7 |
+
|
| 8 |
+
# Remove rows without projects or without mean
|
| 9 |
+
planning = planning.dropna(subset=["mean_eur_per_kw", "projects"])
|
| 10 |
+
permitting = permitting.dropna(subset=["mean_eur_per_kw", "projects"])
|
| 11 |
+
total = total.dropna(subset=["mean_eur_per_kw", "projects"])
|
| 12 |
+
|
| 13 |
+
def weighted_mean(df):
|
| 14 |
+
df = df.dropna(subset=["mean_eur_per_kw", "projects"])
|
| 15 |
+
return (df["mean_eur_per_kw"] * df["projects"]).sum() / df["projects"].sum()
|
| 16 |
+
|
| 17 |
+
# Compute national values
|
| 18 |
+
national_planning = weighted_mean(planning)
|
| 19 |
+
national_permitting = weighted_mean(permitting)
|
| 20 |
+
national_total = weighted_mean(total)
|
| 21 |
+
|
| 22 |
+
# Derive precheck
|
| 23 |
+
national_precheck = national_total - national_planning - national_permitting
|
| 24 |
+
|
| 25 |
+
# Create output table
|
| 26 |
+
national_costs = pd.DataFrame({
|
| 27 |
+
"phase": ["Vorpruefung", "Planung", "Genehmigung", "Total_bis_Genehmigung"],
|
| 28 |
+
"mean_eur_per_kw": [
|
| 29 |
+
national_precheck,
|
| 30 |
+
national_planning,
|
| 31 |
+
national_permitting,
|
| 32 |
+
national_total
|
| 33 |
+
]
|
| 34 |
+
})
|
| 35 |
+
|
| 36 |
+
national_costs.to_csv("national_wind_project_development_costs.csv", index=False)
|
| 37 |
+
|
| 38 |
+
print(national_costs)
|
model/costs/planning/national_project_development_costs.csv
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
phase,weighted_mean_eur_per_kw,projects_used
|
| 2 |
+
Planning,29.03921568627451,204
|
| 3 |
+
Permitting,29.986486486486488,148
|
| 4 |
+
Total_to_Permit,70.06849315068493,146
|
model/costs/planning/national_wind_project_development_costs.csv
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
phase,mean_eur_per_kw
|
| 2 |
+
Vorpruefung,11.042790977923932
|
| 3 |
+
Planung,29.03921568627451
|
| 4 |
+
Genehmigung,29.986486486486488
|
| 5 |
+
Total_bis_Genehmigung,70.06849315068493
|
model/costs/planning/permitting_phase_bundesland.csv
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
bundesland,projects,min_eur_per_kw,max_eur_per_kw,mean_eur_per_kw
|
| 2 |
+
Baden-Wuerttemberg,0,,,
|
| 3 |
+
Bayern,13,15,117,47
|
| 4 |
+
Brandenburg,11,21,55,38
|
| 5 |
+
Bremen,0,,,
|
| 6 |
+
Hessen,4,16,34,25
|
| 7 |
+
Mecklenburg-Vorpommern,2,7,52,30
|
| 8 |
+
Niedersachsen,17,12,60,24
|
| 9 |
+
Nordrhein-Westfalen,6,6,10,8
|
| 10 |
+
Rheinland-Pfalz,16,9,60,23
|
| 11 |
+
Saarland,1,62,62,62
|
| 12 |
+
Sachsen,3,14,53,30
|
| 13 |
+
Sachsen-Anhalt,1,53,53,53
|
| 14 |
+
Schleswig-Holstein,0,,,
|
| 15 |
+
Thueringen,0,,,
|
| 16 |
+
Gesamt,74,6,117,30
|
model/costs/planning/planning_phase_bundesland.csv
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
bundesland,projects,min_eur_per_kw,max_eur_per_kw,mean_eur_per_kw
|
| 2 |
+
Baden-Wuerttemberg,1,100,100,100
|
| 3 |
+
Bayern,14,13,124,55
|
| 4 |
+
Brandenburg,12,15,72,37
|
| 5 |
+
Bremen,0,,,
|
| 6 |
+
Hessen,12,5,69,21
|
| 7 |
+
Mecklenburg-Vorpommern,2,18,48,33
|
| 8 |
+
Niedersachsen,18,9,69,29
|
| 9 |
+
Nordrhein-Westfalen,6,7,24,17
|
| 10 |
+
Rheinland-Pfalz,17,5,40,15
|
| 11 |
+
Saarland,1,40,40,40
|
| 12 |
+
Sachsen,8,4,41,20
|
| 13 |
+
Sachsen-Anhalt,5,6,69,23
|
| 14 |
+
Schleswig-Holstein,1,5,5,5
|
| 15 |
+
Thueringen,5,5,64,27
|
| 16 |
+
Gesamt,102,4,124,29
|
model/costs/planning/total_bundesland.csv
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
bundesland,projects,min_eur_per_kw,max_eur_per_kw,mean_eur_per_kw
|
| 2 |
+
Baden-Wuerttemberg,0,,,
|
| 3 |
+
Bayern,13,50,234,123
|
| 4 |
+
Brandenburg,11,44,134,85
|
| 5 |
+
Bremen,0,,,
|
| 6 |
+
Hessen,4,38,82,56
|
| 7 |
+
Mecklenburg-Vorpommern,2,36,104,70
|
| 8 |
+
Niedersachsen,17,23,140,59
|
| 9 |
+
Nordrhein-Westfalen,5,17,35,28
|
| 10 |
+
Rheinland-Pfalz,16,17,120,46
|
| 11 |
+
Saarland,1,134,134,134
|
| 12 |
+
Sachsen,2,28,44,36
|
| 13 |
+
Sachsen-Anhalt,1,67,67,67
|
| 14 |
+
Schleswig-Holstein,0,,,
|
| 15 |
+
Thueringen,0,,,
|
| 16 |
+
Gesamt,74,17,234,70
|
model/park_gross_mwh_monthly_mock_2015_2046.csv
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
date,park_capacity_mw,mwh_gross
|
| 2 |
+
2015-01-01,50.0,14387.24
|
| 3 |
+
2015-02-01,50.0,12107.57
|
| 4 |
+
2015-03-01,50.0,12850.37
|
| 5 |
+
2015-04-01,50.0,11438.82
|
| 6 |
+
2015-05-01,50.0,10472.28
|
| 7 |
+
2015-06-01,50.0,9019.09
|
| 8 |
+
2015-07-01,50.0,8876.66
|
| 9 |
+
2015-08-01,50.0,9514.59
|
| 10 |
+
2015-09-01,50.0,10141.8
|
| 11 |
+
2015-10-01,50.0,11848.71
|
| 12 |
+
2015-11-01,50.0,12366.89
|
| 13 |
+
2015-12-01,50.0,14314.35
|
| 14 |
+
2016-01-01,50.0,13643.95
|
| 15 |
+
2016-02-01,50.0,12054.36
|
| 16 |
+
2016-03-01,50.0,12047.31
|
| 17 |
+
2016-04-01,50.0,10364.25
|
| 18 |
+
2016-05-01,50.0,9977.09
|
| 19 |
+
2016-06-01,50.0,8626.77
|
| 20 |
+
2016-07-01,50.0,8542.72
|
| 21 |
+
2016-08-01,50.0,8848.35
|
| 22 |
+
2016-09-01,50.0,8827.63
|
| 23 |
+
2016-10-01,50.0,10744.48
|
| 24 |
+
2016-11-01,50.0,11576.21
|
| 25 |
+
2016-12-01,50.0,12973.94
|
| 26 |
+
2017-01-01,50.0,14705.81
|
| 27 |
+
2017-02-01,50.0,13159.2
|
| 28 |
+
2017-03-01,50.0,12471.5
|
| 29 |
+
2017-04-01,50.0,11554.11
|
| 30 |
+
2017-05-01,50.0,10125.46
|
| 31 |
+
2017-06-01,50.0,9295.0
|
| 32 |
+
2017-07-01,50.0,9281.69
|
| 33 |
+
2017-08-01,50.0,9637.22
|
| 34 |
+
2017-09-01,50.0,10282.34
|
| 35 |
+
2017-10-01,50.0,12113.0
|
| 36 |
+
2017-11-01,50.0,12671.76
|
| 37 |
+
2017-12-01,50.0,14225.79
|
| 38 |
+
2018-01-01,50.0,15295.5
|
| 39 |
+
2018-02-01,50.0,12592.58
|
| 40 |
+
2018-03-01,50.0,12383.39
|
| 41 |
+
2018-04-01,50.0,10907.28
|
| 42 |
+
2018-05-01,50.0,10428.07
|
| 43 |
+
2018-06-01,50.0,9583.02
|
| 44 |
+
2018-07-01,50.0,9328.28
|
| 45 |
+
2018-08-01,50.0,9721.26
|
| 46 |
+
2018-09-01,50.0,9994.44
|
| 47 |
+
2018-10-01,50.0,11954.61
|
| 48 |
+
2018-11-01,50.0,13119.51
|
| 49 |
+
2018-12-01,50.0,14372.47
|
| 50 |
+
2019-01-01,50.0,12983.11
|
| 51 |
+
2019-02-01,50.0,10662.15
|
| 52 |
+
2019-03-01,50.0,10938.85
|
| 53 |
+
2019-04-01,50.0,9586.89
|
| 54 |
+
2019-05-01,50.0,8880.27
|
| 55 |
+
2019-06-01,50.0,8228.35
|
| 56 |
+
2019-07-01,50.0,7865.6
|
| 57 |
+
2019-08-01,50.0,8183.19
|
| 58 |
+
2019-09-01,50.0,8821.07
|
| 59 |
+
2019-10-01,50.0,10356.07
|
| 60 |
+
2019-11-01,50.0,11281.52
|
| 61 |
+
2019-12-01,50.0,12423.3
|
| 62 |
+
2020-01-01,50.0,13053.7
|
| 63 |
+
2020-02-01,50.0,11617.85
|
| 64 |
+
2020-03-01,50.0,10838.87
|
| 65 |
+
2020-04-01,50.0,9576.8
|
| 66 |
+
2020-05-01,50.0,9131.13
|
| 67 |
+
2020-06-01,50.0,8121.55
|
| 68 |
+
2020-07-01,50.0,8334.6
|
| 69 |
+
2020-08-01,50.0,8215.14
|
| 70 |
+
2020-09-01,50.0,8874.89
|
| 71 |
+
2020-10-01,50.0,10960.69
|
| 72 |
+
2020-11-01,50.0,11296.22
|
| 73 |
+
2020-12-01,50.0,13147.47
|
| 74 |
+
2021-01-01,50.0,13785.73
|
| 75 |
+
2021-02-01,50.0,11972.09
|
| 76 |
+
2021-03-01,50.0,11897.89
|
| 77 |
+
2021-04-01,50.0,10630.16
|
| 78 |
+
2021-05-01,50.0,10456.95
|
| 79 |
+
2021-06-01,50.0,8515.39
|
| 80 |
+
2021-07-01,50.0,8949.82
|
| 81 |
+
2021-08-01,50.0,9123.17
|
| 82 |
+
2021-09-01,50.0,9457.81
|
| 83 |
+
2021-10-01,50.0,10825.65
|
| 84 |
+
2021-11-01,50.0,12275.01
|
| 85 |
+
2021-12-01,50.0,13578.99
|
| 86 |
+
2022-01-01,50.0,13917.99
|
| 87 |
+
2022-02-01,50.0,11747.02
|
| 88 |
+
2022-03-01,50.0,12508.32
|
| 89 |
+
2022-04-01,50.0,10390.54
|
| 90 |
+
2022-05-01,50.0,9634.66
|
| 91 |
+
2022-06-01,50.0,8798.96
|
| 92 |
+
2022-07-01,50.0,8666.34
|
| 93 |
+
2022-08-01,50.0,9187.65
|
| 94 |
+
2022-09-01,50.0,9619.14
|
| 95 |
+
2022-10-01,50.0,11146.24
|
| 96 |
+
2022-11-01,50.0,12460.34
|
| 97 |
+
2022-12-01,50.0,12966.97
|
| 98 |
+
2023-01-01,50.0,13714.3
|
| 99 |
+
2023-02-01,50.0,11546.07
|
| 100 |
+
2023-03-01,50.0,11932.77
|
| 101 |
+
2023-04-01,50.0,10150.43
|
| 102 |
+
2023-05-01,50.0,10247.37
|
| 103 |
+
2023-06-01,50.0,8794.9
|
| 104 |
+
2023-07-01,50.0,8325.58
|
| 105 |
+
2023-08-01,50.0,8658.53
|
| 106 |
+
2023-09-01,50.0,9582.74
|
| 107 |
+
2023-10-01,50.0,11437.28
|
| 108 |
+
2023-11-01,50.0,12798.86
|
| 109 |
+
2023-12-01,50.0,14792.43
|
| 110 |
+
2024-01-01,50.0,13516.61
|
| 111 |
+
2024-02-01,50.0,11410.27
|
| 112 |
+
2024-03-01,50.0,10790.85
|
| 113 |
+
2024-04-01,50.0,10190.33
|
| 114 |
+
2024-05-01,50.0,9367.07
|
| 115 |
+
2024-06-01,50.0,8348.38
|
| 116 |
+
2024-07-01,50.0,8163.49
|
| 117 |
+
2024-08-01,50.0,8490.93
|
| 118 |
+
2024-09-01,50.0,9354.21
|
| 119 |
+
2024-10-01,50.0,10702.65
|
| 120 |
+
2024-11-01,50.0,11474.82
|
| 121 |
+
2024-12-01,50.0,12584.86
|
| 122 |
+
2025-01-01,50.0,13778.79
|
| 123 |
+
2025-02-01,50.0,12142.34
|
| 124 |
+
2025-03-01,50.0,12507.09
|
| 125 |
+
2025-04-01,50.0,11567.87
|
| 126 |
+
2025-05-01,50.0,10474.09
|
| 127 |
+
2025-06-01,50.0,9457.2
|
| 128 |
+
2025-07-01,50.0,8901.56
|
| 129 |
+
2025-08-01,50.0,8936.54
|
| 130 |
+
2025-09-01,50.0,9564.71
|
| 131 |
+
2025-10-01,50.0,11323.8
|
| 132 |
+
2025-11-01,50.0,13328.93
|
| 133 |
+
2025-12-01,50.0,13766.25
|
| 134 |
+
2026-01-01,50.0,14748.42
|
| 135 |
+
2026-02-01,50.0,11888.24
|
| 136 |
+
2026-03-01,50.0,12769.88
|
| 137 |
+
2026-04-01,50.0,11019.33
|
| 138 |
+
2026-05-01,50.0,10297.59
|
| 139 |
+
2026-06-01,50.0,9098.52
|
| 140 |
+
2026-07-01,50.0,8785.44
|
| 141 |
+
2026-08-01,50.0,9311.53
|
| 142 |
+
2026-09-01,50.0,9634.33
|
| 143 |
+
2026-10-01,50.0,11056.94
|
| 144 |
+
2026-11-01,50.0,11947.98
|
| 145 |
+
2026-12-01,50.0,14068.67
|
| 146 |
+
2027-01-01,50.0,14500.96
|
| 147 |
+
2027-02-01,50.0,11815.79
|
| 148 |
+
2027-03-01,50.0,11912.61
|
| 149 |
+
2027-04-01,50.0,10573.43
|
| 150 |
+
2027-05-01,50.0,10346.92
|
| 151 |
+
2027-06-01,50.0,8824.51
|
| 152 |
+
2027-07-01,50.0,8517.88
|
| 153 |
+
2027-08-01,50.0,9136.23
|
| 154 |
+
2027-09-01,50.0,9520.95
|
| 155 |
+
2027-10-01,50.0,11555.94
|
| 156 |
+
2027-11-01,50.0,12022.43
|
| 157 |
+
2027-12-01,50.0,12974.65
|
| 158 |
+
2028-01-01,50.0,13930.04
|
| 159 |
+
2028-02-01,50.0,13428.58
|
| 160 |
+
2028-03-01,50.0,13191.98
|
| 161 |
+
2028-04-01,50.0,10940.09
|
| 162 |
+
2028-05-01,50.0,10326.61
|
| 163 |
+
2028-06-01,50.0,9601.42
|
| 164 |
+
2028-07-01,50.0,8748.0
|
| 165 |
+
2028-08-01,50.0,9028.79
|
| 166 |
+
2028-09-01,50.0,10052.88
|
| 167 |
+
2028-10-01,50.0,11453.29
|
| 168 |
+
2028-11-01,50.0,12543.05
|
| 169 |
+
2028-12-01,50.0,14062.85
|
| 170 |
+
2029-01-01,50.0,14165.43
|
| 171 |
+
2029-02-01,50.0,12413.74
|
| 172 |
+
2029-03-01,50.0,12142.06
|
| 173 |
+
2029-04-01,50.0,10823.7
|
| 174 |
+
2029-05-01,50.0,9464.78
|
| 175 |
+
2029-06-01,50.0,8866.75
|
| 176 |
+
2029-07-01,50.0,8514.31
|
| 177 |
+
2029-08-01,50.0,8629.15
|
| 178 |
+
2029-09-01,50.0,9270.29
|
| 179 |
+
2029-10-01,50.0,11077.11
|
| 180 |
+
2029-11-01,50.0,12443.47
|
| 181 |
+
2029-12-01,50.0,13100.05
|
| 182 |
+
2030-01-01,50.0,13080.46
|
| 183 |
+
2030-02-01,50.0,10938.48
|
| 184 |
+
2030-03-01,50.0,11173.61
|
| 185 |
+
2030-04-01,50.0,10193.15
|
| 186 |
+
2030-05-01,50.0,9550.01
|
| 187 |
+
2030-06-01,50.0,8607.05
|
| 188 |
+
2030-07-01,50.0,8102.7
|
| 189 |
+
2030-08-01,50.0,8172.45
|
| 190 |
+
2030-09-01,50.0,8813.16
|
| 191 |
+
2030-10-01,50.0,10503.16
|
| 192 |
+
2030-11-01,50.0,11345.78
|
| 193 |
+
2030-12-01,50.0,12300.27
|
| 194 |
+
2031-01-01,50.0,13895.85
|
| 195 |
+
2031-02-01,50.0,11851.1
|
| 196 |
+
2031-03-01,50.0,12870.28
|
| 197 |
+
2031-04-01,50.0,11084.33
|
| 198 |
+
2031-05-01,50.0,9711.16
|
| 199 |
+
2031-06-01,50.0,8699.48
|
| 200 |
+
2031-07-01,50.0,8253.4
|
| 201 |
+
2031-08-01,50.0,8694.29
|
| 202 |
+
2031-09-01,50.0,9498.05
|
| 203 |
+
2031-10-01,50.0,11457.48
|
| 204 |
+
2031-11-01,50.0,11706.28
|
| 205 |
+
2031-12-01,50.0,13217.65
|
| 206 |
+
2032-01-01,50.0,12077.99
|
| 207 |
+
2032-02-01,50.0,11315.41
|
| 208 |
+
2032-03-01,50.0,10792.09
|
| 209 |
+
2032-04-01,50.0,9619.93
|
| 210 |
+
2032-05-01,50.0,9039.84
|
| 211 |
+
2032-06-01,50.0,8151.34
|
| 212 |
+
2032-07-01,50.0,7617.44
|
| 213 |
+
2032-08-01,50.0,7882.38
|
| 214 |
+
2032-09-01,50.0,9324.79
|
| 215 |
+
2032-10-01,50.0,9902.73
|
| 216 |
+
2032-11-01,50.0,10781.98
|
| 217 |
+
2032-12-01,50.0,13251.46
|
| 218 |
+
2033-01-01,50.0,15335.09
|
| 219 |
+
2033-02-01,50.0,11559.66
|
| 220 |
+
2033-03-01,50.0,12045.69
|
| 221 |
+
2033-04-01,50.0,10790.35
|
| 222 |
+
2033-05-01,50.0,10670.37
|
| 223 |
+
2033-06-01,50.0,8667.43
|
| 224 |
+
2033-07-01,50.0,8721.92
|
| 225 |
+
2033-08-01,50.0,9219.33
|
| 226 |
+
2033-09-01,50.0,9701.93
|
| 227 |
+
2033-10-01,50.0,11127.96
|
| 228 |
+
2033-11-01,50.0,12132.91
|
| 229 |
+
2033-12-01,50.0,13157.0
|
| 230 |
+
2034-01-01,50.0,13335.38
|
| 231 |
+
2034-02-01,50.0,11316.77
|
| 232 |
+
2034-03-01,50.0,11678.69
|
| 233 |
+
2034-04-01,50.0,10000.82
|
| 234 |
+
2034-05-01,50.0,9795.92
|
| 235 |
+
2034-06-01,50.0,8763.22
|
| 236 |
+
2034-07-01,50.0,8405.5
|
| 237 |
+
2034-08-01,50.0,8669.03
|
| 238 |
+
2034-09-01,50.0,9133.68
|
| 239 |
+
2034-10-01,50.0,10716.89
|
| 240 |
+
2034-11-01,50.0,11348.31
|
| 241 |
+
2034-12-01,50.0,13191.0
|
| 242 |
+
2035-01-01,50.0,13255.01
|
| 243 |
+
2035-02-01,50.0,12000.15
|
| 244 |
+
2035-03-01,50.0,12020.97
|
| 245 |
+
2035-04-01,50.0,10182.63
|
| 246 |
+
2035-05-01,50.0,9341.51
|
| 247 |
+
2035-06-01,50.0,8136.82
|
| 248 |
+
2035-07-01,50.0,8576.72
|
| 249 |
+
2035-08-01,50.0,8557.58
|
| 250 |
+
2035-09-01,50.0,9155.77
|
| 251 |
+
2035-10-01,50.0,10051.97
|
| 252 |
+
2035-11-01,50.0,11800.05
|
| 253 |
+
2035-12-01,50.0,13109.44
|
| 254 |
+
2036-01-01,50.0,12485.38
|
| 255 |
+
2036-02-01,50.0,11215.29
|
| 256 |
+
2036-03-01,50.0,11240.83
|
| 257 |
+
2036-04-01,50.0,9795.15
|
| 258 |
+
2036-05-01,50.0,9206.99
|
| 259 |
+
2036-06-01,50.0,8152.89
|
| 260 |
+
2036-07-01,50.0,7984.43
|
| 261 |
+
2036-08-01,50.0,8286.88
|
| 262 |
+
2036-09-01,50.0,9156.11
|
| 263 |
+
2036-10-01,50.0,9511.87
|
| 264 |
+
2036-11-01,50.0,11074.78
|
| 265 |
+
2036-12-01,50.0,12631.76
|
| 266 |
+
2037-01-01,50.0,14264.09
|
| 267 |
+
2037-02-01,50.0,11874.61
|
| 268 |
+
2037-03-01,50.0,11565.15
|
| 269 |
+
2037-04-01,50.0,10811.08
|
| 270 |
+
2037-05-01,50.0,10694.76
|
| 271 |
+
2037-06-01,50.0,8540.67
|
| 272 |
+
2037-07-01,50.0,9035.23
|
| 273 |
+
2037-08-01,50.0,8941.18
|
| 274 |
+
2037-09-01,50.0,9581.62
|
| 275 |
+
2037-10-01,50.0,10924.79
|
| 276 |
+
2037-11-01,50.0,12087.62
|
| 277 |
+
2037-12-01,50.0,14291.39
|
| 278 |
+
2038-01-01,50.0,13405.15
|
| 279 |
+
2038-02-01,50.0,11771.63
|
| 280 |
+
2038-03-01,50.0,11778.27
|
| 281 |
+
2038-04-01,50.0,10107.44
|
| 282 |
+
2038-05-01,50.0,9970.52
|
| 283 |
+
2038-06-01,50.0,8452.29
|
| 284 |
+
2038-07-01,50.0,8410.56
|
| 285 |
+
2038-08-01,50.0,8339.81
|
| 286 |
+
2038-09-01,50.0,8962.85
|
| 287 |
+
2038-10-01,50.0,10292.26
|
| 288 |
+
2038-11-01,50.0,11715.67
|
| 289 |
+
2038-12-01,50.0,12364.31
|
| 290 |
+
2039-01-01,50.0,13251.5
|
| 291 |
+
2039-02-01,50.0,10934.18
|
| 292 |
+
2039-03-01,50.0,11573.04
|
| 293 |
+
2039-04-01,50.0,10024.81
|
| 294 |
+
2039-05-01,50.0,9819.97
|
| 295 |
+
2039-06-01,50.0,8378.26
|
| 296 |
+
2039-07-01,50.0,7684.8
|
| 297 |
+
2039-08-01,50.0,8252.93
|
| 298 |
+
2039-09-01,50.0,8481.63
|
| 299 |
+
2039-10-01,50.0,10170.26
|
| 300 |
+
2039-11-01,50.0,11688.58
|
| 301 |
+
2039-12-01,50.0,12837.24
|
| 302 |
+
2040-01-01,50.0,12680.94
|
| 303 |
+
2040-02-01,50.0,11061.75
|
| 304 |
+
2040-03-01,50.0,11195.44
|
| 305 |
+
2040-04-01,50.0,9449.74
|
| 306 |
+
2040-05-01,50.0,9127.38
|
| 307 |
+
2040-06-01,50.0,8278.41
|
| 308 |
+
2040-07-01,50.0,8347.86
|
| 309 |
+
2040-08-01,50.0,8423.76
|
| 310 |
+
2040-09-01,50.0,8189.55
|
| 311 |
+
2040-10-01,50.0,10429.17
|
| 312 |
+
2040-11-01,50.0,11210.06
|
| 313 |
+
2040-12-01,50.0,12757.56
|
| 314 |
+
2041-01-01,50.0,14142.2
|
| 315 |
+
2041-02-01,50.0,10747.12
|
| 316 |
+
2041-03-01,50.0,11440.46
|
| 317 |
+
2041-04-01,50.0,10394.36
|
| 318 |
+
2041-05-01,50.0,9239.91
|
| 319 |
+
2041-06-01,50.0,8919.01
|
| 320 |
+
2041-07-01,50.0,8494.74
|
| 321 |
+
2041-08-01,50.0,8833.61
|
| 322 |
+
2041-09-01,50.0,9000.88
|
| 323 |
+
2041-10-01,50.0,11024.96
|
| 324 |
+
2041-11-01,50.0,12021.88
|
| 325 |
+
2041-12-01,50.0,13213.92
|
| 326 |
+
2042-01-01,50.0,13425.51
|
| 327 |
+
2042-02-01,50.0,11415.19
|
| 328 |
+
2042-03-01,50.0,11213.75
|
| 329 |
+
2042-04-01,50.0,10050.17
|
| 330 |
+
2042-05-01,50.0,9543.79
|
| 331 |
+
2042-06-01,50.0,8538.87
|
| 332 |
+
2042-07-01,50.0,8553.54
|
| 333 |
+
2042-08-01,50.0,8244.49
|
| 334 |
+
2042-09-01,50.0,9017.58
|
| 335 |
+
2042-10-01,50.0,11110.16
|
| 336 |
+
2042-11-01,50.0,11256.56
|
| 337 |
+
2042-12-01,50.0,12650.11
|
| 338 |
+
2043-01-01,50.0,13396.76
|
| 339 |
+
2043-02-01,50.0,11596.42
|
| 340 |
+
2043-03-01,50.0,11502.2
|
| 341 |
+
2043-04-01,50.0,10484.86
|
| 342 |
+
2043-05-01,50.0,9822.43
|
| 343 |
+
2043-06-01,50.0,8644.7
|
| 344 |
+
2043-07-01,50.0,8432.48
|
| 345 |
+
2043-08-01,50.0,9098.68
|
| 346 |
+
2043-09-01,50.0,8985.14
|
| 347 |
+
2043-10-01,50.0,9986.17
|
| 348 |
+
2043-11-01,50.0,12053.19
|
| 349 |
+
2043-12-01,50.0,12776.78
|
| 350 |
+
2044-01-01,50.0,13324.08
|
| 351 |
+
2044-02-01,50.0,12157.69
|
| 352 |
+
2044-03-01,50.0,10916.92
|
| 353 |
+
2044-04-01,50.0,9678.87
|
| 354 |
+
2044-05-01,50.0,9092.4
|
| 355 |
+
2044-06-01,50.0,8209.34
|
| 356 |
+
2044-07-01,50.0,8382.0
|
| 357 |
+
2044-08-01,50.0,8615.93
|
| 358 |
+
2044-09-01,50.0,9091.87
|
| 359 |
+
2044-10-01,50.0,10147.85
|
| 360 |
+
2044-11-01,50.0,10674.76
|
| 361 |
+
2044-12-01,50.0,12941.83
|
| 362 |
+
2045-01-01,50.0,14139.85
|
| 363 |
+
2045-02-01,50.0,12350.01
|
| 364 |
+
2045-03-01,50.0,12645.79
|
| 365 |
+
2045-04-01,50.0,10905.49
|
| 366 |
+
2045-05-01,50.0,10550.01
|
| 367 |
+
2045-06-01,50.0,9144.45
|
| 368 |
+
2045-07-01,50.0,9076.33
|
| 369 |
+
2045-08-01,50.0,8967.01
|
| 370 |
+
2045-09-01,50.0,9685.53
|
| 371 |
+
2045-10-01,50.0,11511.7
|
| 372 |
+
2045-11-01,50.0,12691.48
|
| 373 |
+
2045-12-01,50.0,13788.88
|
| 374 |
+
2046-01-01,50.0,12845.6
|
| 375 |
+
2046-02-01,50.0,10656.8
|
| 376 |
+
2046-03-01,50.0,10882.85
|
| 377 |
+
2046-04-01,50.0,9815.31
|
| 378 |
+
2046-05-01,50.0,8551.96
|
| 379 |
+
2046-06-01,50.0,7697.22
|
| 380 |
+
2046-07-01,50.0,7528.12
|
| 381 |
+
2046-08-01,50.0,7512.55
|
| 382 |
+
2046-09-01,50.0,8412.46
|
| 383 |
+
2046-10-01,50.0,10318.6
|
| 384 |
+
2046-11-01,50.0,10829.41
|
| 385 |
+
2046-12-01,50.0,12377.7
|
model/profit.py
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# power_to_profit.py
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
import pandas as pd
|
| 5 |
+
import numpy_financial as npf
|
| 6 |
+
import sys
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
ROOT = Path(__file__).resolve().parent
|
| 10 |
+
|
| 11 |
+
# Add module folders to Python import path
|
| 12 |
+
sys.path.insert(0, str(ROOT / "revenue"))
|
| 13 |
+
sys.path.insert(0, str(ROOT / "costs" / "capex"))
|
| 14 |
+
sys.path.insert(0, str(ROOT / "costs" / "opex"))
|
| 15 |
+
sys.path.insert(0, str(ROOT / "costs" / "finance"))
|
| 16 |
+
|
| 17 |
+
import revenue_mod as revenue_mod
|
| 18 |
+
import capex_mod as capex_mod
|
| 19 |
+
import opex_mod as opex_mod
|
| 20 |
+
import finance_mod as finance_mod
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
FORECAST_MONTHS = 240 # 20 years
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def _compute_npv(cashflows, discount_rate):
|
| 27 |
+
return sum(cf / ((1 + discount_rate) ** t) for t, cf in enumerate(cashflows))
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def _compute_irr(cashflows, guess=0.08):
|
| 32 |
+
if all(cf >= 0 for cf in cashflows) or all(cf <= 0 for cf in cashflows):
|
| 33 |
+
return np.nan
|
| 34 |
+
|
| 35 |
+
r = guess
|
| 36 |
+
for _ in range(200):
|
| 37 |
+
npv = 0.0
|
| 38 |
+
d_npv = 0.0
|
| 39 |
+
for t, cf in enumerate(cashflows):
|
| 40 |
+
denom = (1 + r) ** t
|
| 41 |
+
npv += cf / denom
|
| 42 |
+
if t > 0:
|
| 43 |
+
d_npv += -t * cf / ((1 + r) ** (t + 1))
|
| 44 |
+
|
| 45 |
+
if abs(npv) < 1e-6:
|
| 46 |
+
return r
|
| 47 |
+
|
| 48 |
+
if abs(d_npv) < 1e-12:
|
| 49 |
+
break
|
| 50 |
+
|
| 51 |
+
r_new = r - (npv / d_npv)
|
| 52 |
+
# If Newton wants to run outside sane bounds, treat as failure
|
| 53 |
+
if r_new <= -0.99 or r_new >= 5.0:
|
| 54 |
+
return np.nan
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
if abs(r_new - r) < 1e-9:
|
| 58 |
+
return r_new
|
| 59 |
+
|
| 60 |
+
r = r_new
|
| 61 |
+
|
| 62 |
+
return np.nan
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def _month_index(dt: pd.Series) -> pd.Series:
|
| 66 |
+
"""Integer month index for easy month-diff calculations: year*12 + (month-1)."""
|
| 67 |
+
return dt.dt.year * 12 + (dt.dt.month - 1)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def power_to_profit(
|
| 71 |
+
mwh_monthly_20y,
|
| 72 |
+
turbine_type_id=1, # 0=LOW_WIND, 1=BALANCED, 2=HIGH_WIND
|
| 73 |
+
n_turbines=12,
|
| 74 |
+
hub_height_m=160,
|
| 75 |
+
equity_eur=None, # <-- absolute € amount (not share)
|
| 76 |
+
debt_rate=0.045,
|
| 77 |
+
equity_return=0.085,
|
| 78 |
+
debt_tenor_years=20,
|
| 79 |
+
discount_rate=None,
|
| 80 |
+
revenue_kwargs=None,
|
| 81 |
+
):
|
| 82 |
+
"""
|
| 83 |
+
Orchestrates: revenue + capex + opex + finance => yearly profit, NPV, IRR
|
| 84 |
+
|
| 85 |
+
IMPORTANT:
|
| 86 |
+
- Yearly aggregation is PROJECT YEARS (12-month blocks from COD),
|
| 87 |
+
not calendar years.
|
| 88 |
+
"""
|
| 89 |
+
|
| 90 |
+
revenue_kwargs = revenue_kwargs or {}
|
| 91 |
+
|
| 92 |
+
# -----------------------
|
| 93 |
+
# 1) Prepare monthly MWh input -> DataFrame(date, mwh)
|
| 94 |
+
# -----------------------
|
| 95 |
+
if isinstance(mwh_monthly_20y, pd.Series):
|
| 96 |
+
mwh_df = mwh_monthly_20y.rename("mwh").to_frame()
|
| 97 |
+
mwh_df = mwh_df.reset_index().rename(columns={"index": "date"})
|
| 98 |
+
elif isinstance(mwh_monthly_20y, pd.DataFrame):
|
| 99 |
+
mwh_df = mwh_monthly_20y.copy()
|
| 100 |
+
if "date" not in mwh_df.columns:
|
| 101 |
+
raise ValueError("mwh_monthly_20y DataFrame must contain a 'date' column.")
|
| 102 |
+
if "mwh" not in mwh_df.columns:
|
| 103 |
+
for alt in ["mwh_gross", "MWh", "MWh_gross", "mwh_gross_park", "mwh_park"]:
|
| 104 |
+
if alt in mwh_df.columns:
|
| 105 |
+
mwh_df = mwh_df.rename(columns={alt: "mwh"})
|
| 106 |
+
break
|
| 107 |
+
if "mwh" not in mwh_df.columns:
|
| 108 |
+
raise ValueError("mwh_monthly_20y must contain an 'mwh' column (or mwh_gross).")
|
| 109 |
+
else:
|
| 110 |
+
raise TypeError("mwh_monthly_20y must be a pandas Series or DataFrame.")
|
| 111 |
+
|
| 112 |
+
mwh_df["date"] = pd.to_datetime(mwh_df["date"], errors="coerce")
|
| 113 |
+
mwh_df["mwh"] = pd.to_numeric(mwh_df["mwh"], errors="coerce")
|
| 114 |
+
mwh_df = mwh_df.dropna(subset=["date", "mwh"]).sort_values("date").reset_index(drop=True)
|
| 115 |
+
|
| 116 |
+
# -----------------------
|
| 117 |
+
# 2) Revenue module (NEW API)
|
| 118 |
+
# -----------------------
|
| 119 |
+
required = ["tso_id", "eeg_on", "cod_date"]
|
| 120 |
+
missing = [k for k in required if k not in revenue_kwargs]
|
| 121 |
+
if missing:
|
| 122 |
+
raise ValueError(
|
| 123 |
+
f"revenue_kwargs missing required keys: {missing}. "
|
| 124 |
+
f"Expected at least: {required} (manual_eeg_strike optional)."
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
tso_id = int(revenue_kwargs["tso_id"])
|
| 128 |
+
eeg_on = int(revenue_kwargs.get("eeg_on", 1))
|
| 129 |
+
manual_eeg_strike = revenue_kwargs.get("manual_eeg_strike", None)
|
| 130 |
+
cod_date = revenue_kwargs["cod_date"]
|
| 131 |
+
|
| 132 |
+
# COD normalized to month-start
|
| 133 |
+
cod = pd.Timestamp(cod_date)
|
| 134 |
+
cod = pd.Timestamp(year=cod.year, month=cod.month, day=1)
|
| 135 |
+
|
| 136 |
+
optional_keys = ["base_dir", "market_file", "cf_file", "curtail_file", "eeg_file"]
|
| 137 |
+
optional_args = {k: revenue_kwargs[k] for k in optional_keys if k in revenue_kwargs}
|
| 138 |
+
|
| 139 |
+
monthly_rev = revenue_mod.generate_monthly_revenue(
|
| 140 |
+
tso_id=tso_id,
|
| 141 |
+
mwh_monthly_20y=mwh_df,
|
| 142 |
+
eeg_on=eeg_on,
|
| 143 |
+
manual_eeg_strike=manual_eeg_strike,
|
| 144 |
+
cod_date=cod,
|
| 145 |
+
forecast_months=FORECAST_MONTHS,
|
| 146 |
+
**optional_args,
|
| 147 |
+
)
|
| 148 |
+
|
| 149 |
+
if "date" not in monthly_rev.columns or "revenue_eur" not in monthly_rev.columns:
|
| 150 |
+
raise ValueError("Revenue output must contain columns: 'date' and 'revenue_eur'.")
|
| 151 |
+
|
| 152 |
+
monthly_rev["date"] = pd.to_datetime(monthly_rev["date"], errors="coerce")
|
| 153 |
+
monthly_rev = monthly_rev.dropna(subset=["date"]).sort_values("date").reset_index(drop=True)
|
| 154 |
+
|
| 155 |
+
print("\n===== REVENUE DRIVERS =====")
|
| 156 |
+
print("Avg delivered MWh / month:", monthly_rev["mwh_delivered"].mean())
|
| 157 |
+
print("Avg realised price €/MWh:", monthly_rev["p_wind_realised"].mean())
|
| 158 |
+
print("Avg revenue per month (k€):", monthly_rev["revenue_eur"].mean() / 1e3)
|
| 159 |
+
print("Avg market price €/MWh:", monthly_rev["p_market"].mean())
|
| 160 |
+
print("Avg capture factor:", monthly_rev["cf"].mean())
|
| 161 |
+
print("Avg curtailment:", monthly_rev["cr"].mean())
|
| 162 |
+
print("==========================\n")
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
# safety net
|
| 166 |
+
monthly_rev = monthly_rev[monthly_rev["date"] >= cod].copy()
|
| 167 |
+
if len(monthly_rev) < FORECAST_MONTHS:
|
| 168 |
+
raise ValueError(f"Revenue series has only {len(monthly_rev)} months from COD, need {FORECAST_MONTHS}.")
|
| 169 |
+
monthly_rev = monthly_rev.head(FORECAST_MONTHS).copy()
|
| 170 |
+
|
| 171 |
+
# -----------------------
|
| 172 |
+
# 2c) Aggregate by PROJECT YEAR (Year 1..20 from COD)
|
| 173 |
+
# -----------------------
|
| 174 |
+
moff = _month_index(monthly_rev["date"]) - (cod.year * 12 + (cod.month - 1))
|
| 175 |
+
monthly_rev["project_month"] = moff + 1
|
| 176 |
+
monthly_rev["project_year"] = (moff // 12) + 1
|
| 177 |
+
|
| 178 |
+
yearly_revenue = (
|
| 179 |
+
monthly_rev.groupby("project_year", as_index=False)["revenue_eur"]
|
| 180 |
+
.sum()
|
| 181 |
+
.sort_values("project_year")
|
| 182 |
+
.reset_index(drop=True)
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
horizon_years = int(np.ceil(FORECAST_MONTHS / 12.0))
|
| 186 |
+
year_starts = [cod + pd.DateOffset(months=12 * (y - 1)) for y in range(1, horizon_years + 1)]
|
| 187 |
+
yearly_revenue["year_start"] = year_starts
|
| 188 |
+
|
| 189 |
+
# -----------------------
|
| 190 |
+
# 3) CAPEX module (CAPEX -> finance dependency handled correctly)
|
| 191 |
+
# -----------------------
|
| 192 |
+
capex_res = capex_mod.windpark_capex(
|
| 193 |
+
n_turbines=n_turbines,
|
| 194 |
+
turbine_type_id=turbine_type_id,
|
| 195 |
+
hub_height_m=hub_height_m,
|
| 196 |
+
)
|
| 197 |
+
capex_total = float(capex_res["total_capex_eur"])
|
| 198 |
+
park_mw = float(capex_res["park_mw"])
|
| 199 |
+
|
| 200 |
+
# -----------------------
|
| 201 |
+
# 4) OPEX module (NEW: aligned to forecast_months, returns project_year already)
|
| 202 |
+
# -----------------------
|
| 203 |
+
opex_df, opex_total = opex_mod.windpark_opex_timeseries(
|
| 204 |
+
park_mw=park_mw,
|
| 205 |
+
forecast_months=FORECAST_MONTHS,
|
| 206 |
+
)
|
| 207 |
+
|
| 208 |
+
# NEW opex.py returns: project_year, annual_opex_eur
|
| 209 |
+
if "project_year" not in opex_df.columns or "annual_opex_eur" not in opex_df.columns:
|
| 210 |
+
raise ValueError("OPEX output must contain columns: 'project_year' and 'annual_opex_eur'.")
|
| 211 |
+
|
| 212 |
+
opex_df = opex_df.sort_values("project_year").reset_index(drop=True)
|
| 213 |
+
|
| 214 |
+
# -----------------------
|
| 215 |
+
# 5) Financing module (NEW: equity_eur input, debt schedule returned)
|
| 216 |
+
# -----------------------
|
| 217 |
+
if equity_eur is None:
|
| 218 |
+
equity_eur = 0.15 * capex_total # default: 15% of capex
|
| 219 |
+
|
| 220 |
+
fin = finance_mod.financing_model(
|
| 221 |
+
capex_eur=capex_total,
|
| 222 |
+
equity_eur=float(equity_eur), # <-- absolute €
|
| 223 |
+
debt_rate=debt_rate,
|
| 224 |
+
equity_return=equity_return,
|
| 225 |
+
debt_tenor_years=debt_tenor_years,
|
| 226 |
+
forecast_months=FORECAST_MONTHS,
|
| 227 |
+
)
|
| 228 |
+
|
| 229 |
+
# aligned yearly debt schedule
|
| 230 |
+
debt_service_df = fin["debt_service_yearly_df"]
|
| 231 |
+
if "project_year" not in debt_service_df.columns or "debt_service_eur" not in debt_service_df.columns:
|
| 232 |
+
raise ValueError("finance.py must return debt_service_yearly_df with columns: project_year, debt_service_eur")
|
| 233 |
+
|
| 234 |
+
debt_service_df = debt_service_df.sort_values("project_year").reset_index(drop=True)
|
| 235 |
+
|
| 236 |
+
print("\n===== DEBT SERVICE SCHEDULE =====")
|
| 237 |
+
print(debt_service_df.head(5))
|
| 238 |
+
print("...")
|
| 239 |
+
print(debt_service_df.tail(5))
|
| 240 |
+
print("================================\n")
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
print("\n===== FINANCIAL SANITY CHECK =====")
|
| 244 |
+
print("Park MW:", park_mw)
|
| 245 |
+
print("CAPEX total (M€):", capex_total / 1e6)
|
| 246 |
+
print("CAPEX €/kW:", capex_res["total_capex_eur_per_kw"])
|
| 247 |
+
print("Equity (M€):", equity_eur / 1e6)
|
| 248 |
+
print("Equity share:", fin.get("equity_share_derived"))
|
| 249 |
+
print("Debt (M€):", fin["debt_eur"] / 1e6)
|
| 250 |
+
|
| 251 |
+
print("Average yearly debt service (M€):",
|
| 252 |
+
debt_service_df["debt_service_eur"].mean() / 1e6)
|
| 253 |
+
|
| 254 |
+
print("=================================\n")
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
# -----------------------
|
| 258 |
+
# 6) Unite yearly cashflows (by project_year)
|
| 259 |
+
# -----------------------
|
| 260 |
+
yearly = pd.DataFrame({
|
| 261 |
+
"project_year": list(range(1, horizon_years + 1)),
|
| 262 |
+
"year_start": year_starts,
|
| 263 |
+
})
|
| 264 |
+
|
| 265 |
+
yearly = yearly.merge(yearly_revenue[["project_year", "revenue_eur"]], on="project_year", how="left")
|
| 266 |
+
yearly = yearly.merge(opex_df[["project_year", "annual_opex_eur"]], on="project_year", how="left")
|
| 267 |
+
yearly = yearly.merge(debt_service_df[["project_year", "debt_service_eur"]], on="project_year", how="left")
|
| 268 |
+
|
| 269 |
+
# Fill any missing (shouldn't happen, but keeps things robust)
|
| 270 |
+
yearly["revenue_eur"] = yearly["revenue_eur"].fillna(0.0)
|
| 271 |
+
yearly["annual_opex_eur"] = yearly["annual_opex_eur"].fillna(0.0)
|
| 272 |
+
yearly["debt_service_eur"] = yearly["debt_service_eur"].fillna(0.0)
|
| 273 |
+
|
| 274 |
+
yearly["profit_after_opex_and_debt_eur"] = (
|
| 275 |
+
yearly["revenue_eur"] - yearly["annual_opex_eur"] - yearly["debt_service_eur"]
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
# -----------------------
|
| 279 |
+
# 7) Equity cashflows + NPV + IRR
|
| 280 |
+
# -----------------------
|
| 281 |
+
equity_cashflows = [-float(equity_eur)] + yearly["profit_after_opex_and_debt_eur"].tolist()
|
| 282 |
+
|
| 283 |
+
# -----------------------
|
| 284 |
+
# Terminal value (residual value at end of year 20)
|
| 285 |
+
# -----------------------
|
| 286 |
+
TERMINAL_VALUE_SHARE = 0.30 # 10% of CAPEX as salvage / repowering option
|
| 287 |
+
terminal_value = TERMINAL_VALUE_SHARE * capex_total
|
| 288 |
+
|
| 289 |
+
equity_cashflows[-1] += terminal_value
|
| 290 |
+
|
| 291 |
+
print(f"Terminal value added in year 20: {terminal_value/1e6:.1f} M€")
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
used_discount_rate = discount_rate if discount_rate is not None else float(fin["wacc"])
|
| 295 |
+
npv_eur = _compute_npv(equity_cashflows, used_discount_rate)
|
| 296 |
+
irr = npf.irr(equity_cashflows)
|
| 297 |
+
|
| 298 |
+
return {
|
| 299 |
+
"monthly_revenue_df": monthly_rev,
|
| 300 |
+
"yearly_df": yearly,
|
| 301 |
+
"capex_summary": {**capex_res},
|
| 302 |
+
"opex_summary": {"total_opex_eur": float(opex_total)},
|
| 303 |
+
"finance_summary": fin | {
|
| 304 |
+
"equity_eur_input": float(equity_eur),
|
| 305 |
+
},
|
| 306 |
+
"equity_cashflows": equity_cashflows,
|
| 307 |
+
"npv_eur": npv_eur,
|
| 308 |
+
"irr": irr,
|
| 309 |
+
"discount_rate_used": used_discount_rate,
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
# -------------------------
|
| 314 |
+
# Example call
|
| 315 |
+
# -------------------------
|
| 316 |
+
if __name__ == "__main__":
|
| 317 |
+
cod = pd.Timestamp.today()
|
| 318 |
+
cod = pd.Timestamp(year=cod.year, month=cod.month, day=1)
|
| 319 |
+
|
| 320 |
+
dates = pd.date_range(cod, periods=FORECAST_MONTHS, freq="MS")
|
| 321 |
+
example_mwh = pd.Series(24000.0, index=dates)
|
| 322 |
+
|
| 323 |
+
result = power_to_profit(
|
| 324 |
+
mwh_monthly_20y=example_mwh,
|
| 325 |
+
turbine_type_id=1,
|
| 326 |
+
n_turbines=12,
|
| 327 |
+
hub_height_m=160,
|
| 328 |
+
equity_eur=60_000_000,
|
| 329 |
+
revenue_kwargs={
|
| 330 |
+
"tso_id": 0,
|
| 331 |
+
"eeg_on": 1,
|
| 332 |
+
"manual_eeg_strike": None,
|
| 333 |
+
"cod_date": str(cod.date()),
|
| 334 |
+
# If you run from a different working dir, set:
|
| 335 |
+
# "base_dir": str(ROOT),
|
| 336 |
+
}
|
| 337 |
+
)
|
| 338 |
+
|
| 339 |
+
print("NPV (equity):", f"{result['npv_eur']/1e6:.1f} M€")
|
| 340 |
+
print("IRR (equity):", f"{result['irr']*100:.2f}%")
|
| 341 |
+
print(result["yearly_df"].head())
|
| 342 |
+
print(result["yearly_df"].tail(5))
|
| 343 |
+
|
| 344 |
+
|
model/revenue/capture_factor_history_forecast/capture_factor_forecast_b2.csv
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
month,cf_hist,wind_mwh_hist,wind_mwh_low,cf_low,wind_mwh_base,cf_base,wind_mwh_high,cf_high
|
| 2 |
+
2015-01-01,0.7971657646881044,7830853.25,,,,,,
|
| 3 |
+
2015-02-01,0.8690542944179981,5325677.75,,,,,,
|
| 4 |
+
2015-03-01,0.8255342879088481,7010958.25,,,,,,
|
| 5 |
+
2015-04-01,0.8730305964403778,5157796.5,,,,,,
|
| 6 |
+
2015-05-01,0.9108853171899532,5105062.25,,,,,,
|
| 7 |
+
2015-06-01,0.9352319647730498,3871212.5,,,,,,
|
| 8 |
+
2015-07-01,0.8438483980050792,5401805.25,,,,,,
|
| 9 |
+
2015-08-01,0.9394317407515804,3553163.75,,,,,,
|
| 10 |
+
2015-09-01,0.8796387097310245,5328808.5,,,,,,
|
| 11 |
+
2015-10-01,0.9307452220979952,3438960.5,,,,,,
|
| 12 |
+
2015-11-01,0.8363187233591128,9763092.0,,,,,,
|
| 13 |
+
2015-12-01,0.8596254975904842,10359892.25,,,,,,
|
| 14 |
+
2016-01-01,0.843399934260027,8406655.5,,,,,,
|
| 15 |
+
2016-02-01,0.8476904277698321,9366679.75,,,,,,
|
| 16 |
+
2016-03-01,0.885148550782457,5710792.5,,,,,,
|
| 17 |
+
2016-04-01,0.9594746283445816,5587231.75,,,,,,
|
| 18 |
+
2016-05-01,0.840229734804759,5706867.75,,,,,,
|
| 19 |
+
2016-06-01,0.9633910888369888,2902409.5,,,,,,
|
| 20 |
+
2016-07-01,0.8833173371246897,4302145.75,,,,,,
|
| 21 |
+
2016-08-01,0.9387251967374728,4262079.75,,,,,,
|
| 22 |
+
2016-09-01,0.9116825453835888,3729333.5,,,,,,
|
| 23 |
+
2016-10-01,0.912104248421158,4488192.0,,,,,,
|
| 24 |
+
2016-11-01,0.8668111264786234,7267011.75,,,,,,
|
| 25 |
+
2016-12-01,0.6650078674754464,8416867.75,,,,,,
|
| 26 |
+
2017-01-01,0.796002572213315,7186927.25,,,,,,
|
| 27 |
+
2017-02-01,0.8310610612983536,8439755.75,,,,,,
|
| 28 |
+
2017-03-01,0.916222166975428,8511720.0,,,,,,
|
| 29 |
+
2017-04-01,0.8584551912833392,7421613.0,,,,,,
|
| 30 |
+
2017-05-01,0.8703020447211074,4963043.75,,,,,,
|
| 31 |
+
2017-06-01,0.85696744583063,6153125.0,,,,,,
|
| 32 |
+
2017-07-01,0.8963757838970061,5011439.25,,,,,,
|
| 33 |
+
2017-08-01,0.8851074120163239,4804535.25,,,,,,
|
| 34 |
+
2017-09-01,0.8240239875515648,5904335.5,,,,,,
|
| 35 |
+
2017-10-01,0.7110785406630726,11014475.5,,,,,,
|
| 36 |
+
2017-11-01,0.7781521585823284,9256318.75,,,,,,
|
| 37 |
+
2017-12-01,0.7368746365402401,13454183.0,,,,,,
|
| 38 |
+
2018-01-01,0.7662484585750495,13144978.0,,,,,,
|
| 39 |
+
2018-02-01,0.9003090338258714,6859993.0,,,,,,
|
| 40 |
+
2018-03-01,0.8148924669900246,9588788.75,,,,,,
|
| 41 |
+
2018-04-01,0.9190437359638376,8002044.25,,,,,,
|
| 42 |
+
2018-05-01,0.8446908004296617,6270346.75,,,,,,
|
| 43 |
+
2018-06-01,0.891257853677082,5135329.25,,,,,,
|
| 44 |
+
2018-07-01,0.9505727463099204,4064678.75,,,,,,
|
| 45 |
+
2018-08-01,0.9364000264231565,5343261.5,,,,,,
|
| 46 |
+
2018-09-01,0.8825727774185559,6545188.25,,,,,,
|
| 47 |
+
2018-10-01,0.8249529792385146,8733167.0,,,,,,
|
| 48 |
+
2018-11-01,0.9212191950381042,8035869.5,,,,,,
|
| 49 |
+
2018-12-01,0.8294148831145396,12092006.75,,,,,,
|
| 50 |
+
2019-01-01,0.7913858813006717,12551354.25,,,,,,
|
| 51 |
+
2019-02-01,0.8977788571766797,8914979.0,,,,,,
|
| 52 |
+
2019-03-01,0.8067350106096033,13736642.0,,,,,,
|
| 53 |
+
2019-04-01,0.9219362017284696,7303645.75,,,,,,
|
| 54 |
+
2019-05-01,0.9491406744264954,6428337.75,,,,,,
|
| 55 |
+
2019-06-01,0.7478043560132084,5114514.5,,,,,,
|
| 56 |
+
2019-07-01,0.9210644724288692,4862707.5,,,,,,
|
| 57 |
+
2019-08-01,0.8332421822301923,4493530.5,,,,,,
|
| 58 |
+
2019-09-01,0.8641271028355628,7145538.75,,,,,,
|
| 59 |
+
2019-10-01,0.8761714169867824,9341217.0,,,,,,
|
| 60 |
+
2019-11-01,0.9046159763857736,7880445.25,,,,,,
|
| 61 |
+
2019-12-01,0.8298915951927173,12208935.0,,,,,,
|
| 62 |
+
2020-01-01,0.8892173696652799,12670559.0,,,,,,
|
| 63 |
+
2020-02-01,0.801370670148446,17239833.25,,,,,,
|
| 64 |
+
2020-03-01,0.8173275716339073,11552708.75,,,,,,
|
| 65 |
+
2020-04-01,0.6561987925727963,6991474.0,,,,,,
|
| 66 |
+
2020-05-01,0.7418702532802646,6132951.75,,,,,,
|
| 67 |
+
2020-06-01,0.8489769334655407,4983084.0,,,,,,
|
| 68 |
+
2020-07-01,0.7245227771392173,5480898.5,,,,,,
|
| 69 |
+
2020-08-01,0.8639570295298692,5156488.25,,,,,,
|
| 70 |
+
2020-09-01,0.8713188572706236,4632294.25,,,,,,
|
| 71 |
+
2020-10-01,0.8859669990959038,10816688.5,,,,,,
|
| 72 |
+
2020-11-01,0.8295916172231614,8665897.5,,,,,,
|
| 73 |
+
2020-12-01,0.7772918524357464,9073761.0,,,,,,
|
| 74 |
+
2021-01-01,0.8838423830800066,9223364.5,,,,,,
|
| 75 |
+
2021-02-01,0.9033426083189586,8487553.25,,,,,,
|
| 76 |
+
2021-03-01,0.743485203895938,9086611.25,,,,,,
|
| 77 |
+
2021-04-01,0.8399588953639053,7735461.0,,,,,,
|
| 78 |
+
2021-05-01,0.809950076338887,8828518.25,,,,,,
|
| 79 |
+
2021-06-01,0.8650260832050826,3361513.75,,,,,,
|
| 80 |
+
2021-07-01,0.85478206431339,4704354.75,,,,,,
|
| 81 |
+
2021-08-01,0.8902143299225604,6191015.5,,,,,,
|
| 82 |
+
2021-09-01,0.9231758067302543,4465397.5,,,,,,
|
| 83 |
+
2021-10-01,0.8028855536070918,10167443.25,,,,,,
|
| 84 |
+
2021-11-01,0.8091082944249354,7822972.75,,,,,,
|
| 85 |
+
2021-12-01,0.7496126000956357,9782408.0,,,,,,
|
| 86 |
+
2022-01-01,0.7889801281913014,12982727.75,,,,,,
|
| 87 |
+
2022-02-01,0.8596946300768242,17728127.25,,,,,,
|
| 88 |
+
2022-03-01,0.8179331024127248,6793504.0,,,,,,
|
| 89 |
+
2022-04-01,0.7914207750015567,9550806.0,,,,,,
|
| 90 |
+
2022-05-01,0.7913465861919791,6454706.0,,,,,,
|
| 91 |
+
2022-06-01,0.9105198867698971,4412514.75,,,,,,
|
| 92 |
+
2022-07-01,0.8987415020852123,5502496.0,,,,,,
|
| 93 |
+
2022-08-01,0.9925071049033212,3527019.25,,,,,,
|
| 94 |
+
2022-09-01,0.8340116597492033,6189613.5,,,,,,
|
| 95 |
+
2022-10-01,0.8467040971896496,8613400.25,,,,,,
|
| 96 |
+
2022-11-01,0.7997193134836902,10118516.25,,,,,,
|
| 97 |
+
2022-12-01,0.6093778772271731,9410138.25,,,,,,
|
| 98 |
+
2023-01-01,0.7627862272091563,14692525.75,,,,,,
|
| 99 |
+
2023-02-01,0.837630935069364,10445029.0,,,,,,
|
| 100 |
+
2023-03-01,0.8509837017682864,12133716.25,,,,,,
|
| 101 |
+
2023-04-01,0.9055675186026236,8382426.5,,,,,,
|
| 102 |
+
2023-05-01,1.0098968064125304,6771381.25,,,,,,
|
| 103 |
+
2023-06-01,0.9829993685400272,4872287.25,,,,,,
|
| 104 |
+
2023-07-01,0.8004890662131304,8392192.75,,,,,,
|
| 105 |
+
2023-08-01,0.7339691885049526,5778036.5,,,,,,
|
| 106 |
+
2023-09-01,0.878258506831602,5339625.25,,,,,,
|
| 107 |
+
2023-10-01,0.8082344425554973,11857250.75,,,,,,
|
| 108 |
+
2023-11-01,0.8488888543617532,14477253.5,,,,,,
|
| 109 |
+
2023-12-01,0.6786395758987744,16331164.75,,,,,,
|
| 110 |
+
2024-01-01,0.8575479503325244,15593084.75,,,,,,
|
| 111 |
+
2024-02-01,0.8818434631285619,14148354.0,,,,,,
|
| 112 |
+
2024-03-01,0.8673996697790639,9393471.75,,,,,,
|
| 113 |
+
2024-04-01,0.81147041545214,9724048.5,,,,,,
|
| 114 |
+
2024-05-01,0.8936559177774147,6274470.0,,,,,,
|
| 115 |
+
2024-06-01,0.8213854820827964,5693810.5,,,,,,
|
| 116 |
+
2024-07-01,0.7962444278290781,5548569.25,,,,,,
|
| 117 |
+
2024-08-01,0.8161256180272725,5204624.75,,,,,,
|
| 118 |
+
2024-09-01,0.8333547783596332,8986503.75,,,,,,
|
| 119 |
+
2024-10-01,0.8103438589199886,8389045.5,,,,,,
|
| 120 |
+
2024-11-01,0.7996357070589065,10300191.5,,,,,,
|
| 121 |
+
2024-12-01,0.678921664750227,13757540.0,,,,,,
|
| 122 |
+
2025-01-01,0.7624826815595828,13253343.0,,,,,,
|
| 123 |
+
2025-02-01,0.9039940754471032,7260679.75,,,,,,
|
| 124 |
+
2025-03-01,0.8461786901389727,6526920.5,,,,,,
|
| 125 |
+
2025-04-01,0.995593530428029,5876514.75,,,,,,
|
| 126 |
+
2025-05-01,0.9731317396080782,7894329.5,,,,,,
|
| 127 |
+
2025-06-01,0.8898558714550471,8705267.75,,,,,,
|
| 128 |
+
2025-07-01,0.9453370489262092,6193497.28,,,,,,
|
| 129 |
+
2025-08-01,0.9180756708029312,5483354.49,,,,,,
|
| 130 |
+
2025-09-01,0.7932076348765756,9763607.04,,,,,,
|
| 131 |
+
2025-10-01,0.6984761049626177,13717685.62,,,,,,
|
| 132 |
+
2025-11-01,0.8786533220749594,9908591.42,,,,,,
|
| 133 |
+
2025-12-01,0.8957505447033655,12331010.68,,,,,,
|
| 134 |
+
2026-01-01,,,13103059.484574642,0.8492030747426846,13244361.45920035,0.8483026536483922,13456531.710088486,0.846970275358313
|
| 135 |
+
2026-02-01,,,13689202.763027957,0.8479966013963295,13848246.970530061,0.8467726649271549,14087302.693321768,0.8449624334085396
|
| 136 |
+
2026-03-01,,,9853240.617301166,0.8200502205273487,9975945.412549093,0.8187104482705418,10160569.296187991,0.8167293616956085
|
| 137 |
+
2026-04-01,,,8533402.529355861,0.8441655622383798,8646802.502112843,0.8426718790898418,8817601.133243259,0.8404635807784577
|
| 138 |
+
2026-05-01,,,6941277.461347821,0.8598682058847109,7039325.437522491,0.8582435082662649,7187152.922073533,0.855841873297681
|
| 139 |
+
2026-06-01,,,4699670.560019861,0.8792027800737486,4769989.096843592,0.8774399093354863,4876117.474608206,0.8748344007231785
|
| 140 |
+
2026-07-01,,,5972682.425109518,0.8519568326478111,6067052.119957717,0.8501511869876742,6209625.822393165,0.8474828366845745
|
| 141 |
+
2026-08-01,,,5214603.942758426,0.8734667751366975,5301368.1288230885,0.8715160015609547,5432585.876867274,0.8686335922980556
|
| 142 |
+
2026-09-01,,,5974607.4885946335,0.8592582369012907,6079030.8134803735,0.8572413748189331,6237117.332225739,0.8542617368285655
|
| 143 |
+
2026-10-01,,,10060336.32471937,0.8108437221831425,10244618.665359516,0.8088482236576238,10523889.963258559,0.8059005645923316
|
| 144 |
+
2026-11-01,,,10375679.56313895,0.828251579887865,10574459.544784559,0.826119001294311,10876010.372046163,0.8229692995780001
|
| 145 |
+
2026-12-01,,,11788004.199059997,0.7441170188677465,12023758.447539996,0.7421164148082282,12381766.44616,0.7391620503393418
|
| 146 |
+
2027-01-01,,,13168574.781997515,0.8051499597737084,13443026.881088354,0.8028936777033087,13860227.661391139,0.7995622157076347
|
| 147 |
+
2027-02-01,,,13757648.776843095,0.8348270672077652,14055970.67508801,0.8323926685443391,14509921.774121422,0.8287987211342658
|
| 148 |
+
2027-03-01,,,9902506.82038767,0.8160031900945485,10125584.593737328,0.813530882402419,10465386.375073629,0.8098814856312622
|
| 149 |
+
2027-04-01,,,8576069.54200264,0.8425622184517824,8776504.539644536,0.8399136329057572,9082129.167240558,0.836004583899231
|
| 150 |
+
2027-05-01,,,6975983.848654561,0.858979312182233,7144915.319085329,0.8561814540670567,7402767.509735739,0.8520526778462385
|
| 151 |
+
2027-06-01,,,4723168.91281996,0.8785105766984712,4841538.9332962455,0.8755492266506828,5022400.998846453,0.8711798050374514
|
| 152 |
+
2027-07-01,,,6002545.837235065,0.8513458378202918,6158057.901757083,0.8483792811315463,6395914.59706496,0.8440027965105219
|
| 153 |
+
2027-08-01,,,5240676.962472217,0.8728577891566051,5380888.650755433,0.869717063381894,5595563.453173293,0.8650842871608452
|
| 154 |
+
2027-09-01,,,6004480.5260376055,0.8586640379614583,6170216.275682578,0.8554767990627234,6424230.852192512,0.8507760781091576
|
| 155 |
+
2027-10-01,,,10110638.006342966,0.8102843137570893,10398287.945339905,0.8071845770456438,10839606.662156317,0.8026135561005525
|
| 156 |
+
2027-11-01,,,10427557.960954644,0.8276805425945527,10733076.437956328,0.8244202141735054,11202290.68320755,0.8196130571846552
|
| 157 |
+
2027-12-01,,,11846944.220055297,0.7436040854692202,12204114.824253095,0.7405904638316432,12753219.4395448,0.7361476897218651
|
| 158 |
+
2028-01-01,,,13234417.655907499,0.8045949852482717,13644672.284304678,0.8012427856797019,14276034.491232876,0.7963015687026807
|
| 159 |
+
2028-02-01,,,13826437.020727308,0.8342516456662152,14266810.235214328,0.8306811302292898,14945219.427345064,0.8254188553899853
|
| 160 |
+
2028-03-01,,,9952019.354489608,0.8154407457545062,10277468.362643387,0.8118581295370708,10779347.966325838,0.8065787674116687
|
| 161 |
+
2028-04-01,,,8618949.889712652,0.841981468564351,8908152.107739203,0.8381866335052264,9354593.042257775,0.8325953357185459
|
| 162 |
+
2028-05-01,,,7010863.767897832,0.8583872467523311,7252089.048871608,0.854421005583623,7624850.535027811,0.848577985337047
|
| 163 |
+
2028-06-01,,,4746784.75738406,0.8779050490886193,4914162.017295688,0.8737489549343262,5173073.028811846,0.8676271116781111
|
| 164 |
+
2028-07-01,,,6032558.566421239,0.8507590339624741,6250428.770283437,0.8466348752622951,6587792.034976908,0.8405609316987592
|
| 165 |
+
2028-08-01,,,5266880.347284579,0.8722561578440794,5461601.980516765,0.8679287835646984,5763430.356768491,0.8615564515004304
|
| 166 |
+
2028-09-01,,,6034502.928667793,0.8580721899222994,6262769.519817815,0.8537177995477595,6616957.777758287,0.8473065916894749
|
| 167 |
+
2028-10-01,,,10161191.196374679,0.8097258122236144,10554262.264520004,0.8055248741983562,11164794.862021007,0.7993404776672501
|
| 168 |
+
2028-11-01,,,10479695.750759415,0.8271100504298508,10894072.58452567,0.8227250720515551,11538359.403703775,0.8162706543549908
|
| 169 |
+
2028-12-01,,,11906178.941155571,0.7430915443587958,12387176.546616893,0.7390676893184154,13135816.022731146,0.7331456607771257
|
| 170 |
+
2029-01-01,,,13300589.744187037,0.8040404051763852,13849342.368569247,0.7995953001225402,14704315.525969861,0.7930542307141804
|
| 171 |
+
2029-02-01,,,13895569.205830945,0.8336766242627695,14480812.38874254,0.8289731146451039,15393576.010165416,0.8220527763680673
|
| 172 |
+
2029-03-01,,,10001779.451262055,0.8148786900672492,10431630.388083037,0.8101888171054592,11102728.405315615,0.8032895187462434
|
| 173 |
+
2029-04-01,,,8662044.639161216,0.8414011192557894,9041774.389355289,0.836463185384902,9635230.833525507,0.8291999908278794
|
| 174 |
+
2029-05-01,,,7045918.08673732,0.8577955894965248,7360870.384604681,0.8526641769524143,7853596.0510786455,0.845117462795974
|
| 175 |
+
2029-06-01,,,4770518.681170979,0.8772999388727262,4987874.447555123,0.8719523848939292,5328265.219676202,0.8640889063168025
|
| 176 |
+
2029-07-01,,,6062721.359253344,0.8501726345753781,6344185.201837688,0.8448940561820982,6785425.796026216,0.8371331029057067
|
| 177 |
+
2029-08-01,,,5293214.749021,0.8716549412175943,5543526.010224516,0.8661441807437796,5936333.267471545,0.8580430024452566
|
| 178 |
+
2029-09-01,,,6064675.443311132,0.8574807498244952,6356711.062615082,0.8519624168225963,6815466.511091036,0.8438512539239348
|
| 179 |
+
2029-10-01,,,10211997.152356552,0.8091676956464771,10712576.198487803,0.8038685839703603,11499738.707881637,0.7960807469309402
|
| 180 |
+
2029-11-01,,,10532094.229513213,0.826539951486118,11057483.673293553,0.8210334154177087,11884510.18581489,0.8129418819288599
|
| 181 |
+
2029-12-01,,,11965709.835861348,0.74257935652561,12572984.194816144,0.7375480458774061,13529890.50341308,0.7301558741825546
|
| 182 |
+
2030-01-01,,,13367092.69290797,0.8034862073577619,14057082.504097786,0.7979512020637907,15145444.991748959,0.7898201354523412
|
| 183 |
+
2030-02-01,,,13965047.051860096,0.833101999202102,14698024.574573679,0.8272686110189132,15855383.29047038,0.8187004243017532
|
| 184 |
+
2030-03-01,,,10051788.348518364,0.814317021785941,10588104.843904283,0.8085229370518624,11435810.257475084,0.8000136837202797
|
| 185 |
+
2030-04-01,,,8705354.86235702,0.8408211699623502,9177401.005195618,0.8347432809543778,9924287.758531272,0.8258184922397707
|
| 186 |
+
2030-05-01,,,7081147.677171006,0.8572043400500257,7471283.440373751,0.8509109606467676,8089203.932611005,0.8416710523535702
|
| 187 |
+
2030-06-01,,,4794371.2745768335,0.8766952457388096,5062692.56426845,0.8701595088938993,5488113.176266489,0.8605651298466735
|
| 188 |
+
2030-07-01,,,6093034.966049612,0.8495866393735183,6439347.979865254,0.8431568165092219,6988988.569907002,0.83371925288539
|
| 189 |
+
2030-08-01,,,5319680.822766105,0.871054138989367,5626678.900377883,0.8643632473566772,6114423.265495692,0.8545438813244176
|
| 190 |
+
2030-09-01,,,6094998.820527687,0.8568897173863181,6452061.7285543075,0.8502106434499773,7019930.506423767,0.8404100071134173
|
| 191 |
+
2030-10-01,,,10263057.138118334,0.8086099637601931,10873264.84146512,0.8022156993446087,11844730.869118087,0.7928343094592274
|
| 192 |
+
2030-11-01,,,10584754.700660778,0.825970245492278,11223345.928392954,0.819345237105192,12241045.491389336,0.8096266843210882
|
| 193 |
+
2030-12-01,,,12025538.385040654,0.7420675217261502,12761578.957738385,0.7360315270706096,13935787.218515472,0.7271782800135259
|
| 194 |
+
2031-01-01,,,13433928.15637251,0.8029323915289246,14267938.74165925,0.7963104845382003,15599808.341501426,0.7865992289129847
|
| 195 |
+
2031-02-01,,,14034872.287119396,0.8325277702110265,14918494.943192283,0.8255676121295594,16331044.789184494,0.8153617432121694
|
| 196 |
+
2031-03-01,,,10102047.290260956,0.8137557406435558,10746926.416562846,0.8068604823187515,11778884.565199336,0.7967512076326151
|
| 197 |
+
2031-04-01,,,8748881.636668803,0.8402416204083165,9315062.020273551,0.8330269129272503,10222016.391287211,0.8224507834886473
|
| 198 |
+
2031-05-01,,,7116553.41555686,0.8566134981317443,7583352.691979356,0.8491613492391543,8331880.050589337,0.8382386964603389
|
| 199 |
+
2031-06-01,,,4818343.130949717,0.8760909693993897,5138632.9527324755,0.8683703193386879,5652756.571554483,0.85705572342634
|
| 200 |
+
2031-07-01,,,6123500.140879858,0.8490010480783035,6535938.199563231,0.8414231488838217,7198658.227004213,0.8303193246320187
|
| 201 |
+
2031-08-01,,,5346279.226879935,0.8704537508737664,5711079.083883551,0.8625859758584377,6297855.963460564,0.851059029708235
|
| 202 |
+
2031-09-01,,,6125473.814630324,0.8562990923267831,6548842.654482621,0.8484624720084862,7230528.421616481,0.836982793794651
|
| 203 |
+
2031-10-01,,,10314372.423808923,0.8080526162996082,11036363.814087093,0.8005662133186292,12200072.795191629,0.7896011110418423
|
| 204 |
+
2031-11-01,,,10637678.47416408,0.8254009321774841,11391696.117318848,0.8176605299620106,12608276.856131017,0.8063250061732227
|
| 205 |
+
2031-12-01,,,12085666.076965857,0.7415560397170822,12953002.64210446,0.7345181264732698,14353860.835070938,0.7242128285490202
|
| 206 |
+
2032-01-01,,,13501097.797154369,0.8023789574265805,14481957.822784137,0.7946731405948446,16067802.59174647,0.7833914573121663
|
| 207 |
+
2032-02-01,,,14105046.648554994,0.8319539370165457,15142272.367340164,0.8238701107707332,16820976.132860027,0.8120366773487253
|
| 208 |
+
2032-03-01,,,10152557.52671226,0.813194846373251,10908130.312811287,0.8052014458631108,12132251.102155317,0.7935020360051604
|
| 209 |
+
2032-04-01,,,8792626.044852147,0.8396624703181607,9454787.950577654,0.831314074032099,10528676.883025827,0.8190968083392035
|
| 210 |
+
2032-05-01,,,7152136.182634645,0.8560230634607856,7697102.982359046,0.8474153353173173,8581836.452107018,0.8348203378014722
|
| 211 |
+
2032-06-01,,,4842434.8466044655,0.8754871095671838,5215712.4470234625,0.8665848086483648,5822339.2687011175,0.8535606284543742
|
| 212 |
+
2032-07-01,,,6154117.641584257,0.8484158604113348,6633977.272556679,0.8396930459611868,7414617.973814339,0.8269332613722746
|
| 213 |
+
2032-08-01,,,5373010.623014334,0.8698537765853588,5796745.270141803,0.860812358719622,6486791.64236438,0.8475883894053061
|
| 214 |
+
2032-09-01,,,6156101.183703475,0.8557088743650968,6647075.294299861,0.8467178950919665,7447444.274264975,0.8335695567387003
|
| 215 |
+
2032-10-01,,,10365944.285927966,0.8074956529997506,11201909.271298401,0.7989201189043467,12566074.979047377,0.7863810976895858
|
| 216 |
+
2032-11-01,,,10690866.866534898,0.8248320112710753,11562571.55907863,0.8159792868508753,12986525.161814947,0.8030367923525628
|
| 217 |
+
2032-12-01,,,12146094.407350685,0.7410449102552389,13147297.681736026,0.7330078376738405,14784476.660123067,0.7212594702707794
|
| 218 |
+
2033-01-01,,,13568603.28614014,0.8018259047876185,14699187.190125898,0.7930391632970883,16549836.669498866,0.7801967670852735
|
| 219 |
+
2033-02-01,,,14175571.881797764,0.8313804993458498,15369406.452850264,0.8221760997509426,17325605.41684583,0.8087251711881847
|
| 220 |
+
2033-03-01,,,10203320.31434582,0.8126343387083697,11071752.267503455,0.8035458206564055,12496218.635219976,0.7902661145819905
|
| 221 |
+
2033-04-01,,,8836589.175076408,0.8390837194165464,9596609.76983632,0.8296047570124536,10844537.189516604,0.8157565107854641
|
| 222 |
+
2033-05-01,,,7187896.863547817,0.8554330357564479,7812559.52709443,0.8456729114842396,8839291.545670226,0.8314159192958938
|
| 223 |
+
2033-06-01,,,4866647.020837488,0.8748836659551077,5293948.133728814,0.8648029692585852,5997009.446762151,0.8500797865683272
|
| 224 |
+
2033-07-01,,,6184888.229792177,0.8478310760944049,6733486.931645028,0.8379665004117082,7637056.51302877,0.8235610065643622
|
| 225 |
+
2033-08-01,,,5399875.676129405,0.8692542158389073,5883696.449193929,0.8590423884262725,6681395.391635312,0.8441319024615356
|
| 226 |
+
2033-09-01,,,6186881.6896219915,0.8551190632206611,6746781.423714358,0.84497690530949,7670867.602492924,0.830170238950011
|
| 227 |
+
2033-10-01,,,10417774.007357607,0.8069390735958308,11369937.910367874,0.7972774091280567,12943057.228418801,0.7831742156334273
|
| 228 |
+
2033-11-01,,,10744321.200867571,0.8242634825025775,11736010.132464807,0.8143015006491727,13376120.916669395,0.7997619879512408
|
| 229 |
+
2033-12-01,,,12206824.879387435,0.7405341330976217,13344507.146962065,0.7315006542739587,15228010.959926758,0.7183181558624839
|
| 230 |
+
2034-01-01,,,13636446.302570838,0.8012732333491085,14919674.997977784,0.7914085457225608,17046331.769583832,0.7770151048861319
|
| 231 |
+
2034-02-01,,,14246449.741206754,0.8308074569263182,15599947.549643017,0.8204855718934827,17845373.5793512,0.8054271694337342
|
| 232 |
+
2034-03-01,,,10254336.915917547,0.8120742173824373,11237828.551516006,0.8018935996845519,12871105.194276575,0.7870433893284347
|
| 233 |
+
2034-04-01,,,8880772.120951787,0.8385053674283266,9740558.916383862,0.8278989546267658,11169873.3052021,0.8124298350498464
|
| 234 |
+
2034-05-01,,,7223836.3478655545,0.8548434147382226,7929747.920000847,0.8439340703581155,9104470.292040335,0.8280253840953047
|
| 235 |
+
2034-06-01,,,4890980.255941674,0.8742806382762747,5373357.355734745,0.8630247936205575,6176919.730165016,0.8466131396437531
|
| 236 |
+
2034-07-01,,,6215812.670941138,0.8472466948494978,6834489.235619703,0.8362435049208474,7866168.208419633,0.8202025038970644
|
| 237 |
+
2034-08-01,,,5426875.054510051,0.8686550683493713,5971951.895931838,0.8572760574798807,6881837.253384371,0.8406895111591659
|
| 238 |
+
2034-09-01,,,6217816.098070102,0.8545296586130706,6847983.145070072,0.8432394952853253,7900993.630567713,0.8267847836654584
|
| 239 |
+
2034-10-01,,,10469862.877394393,0.8063828778232435,11540486.979023391,0.7956380770303919,13331348.945271365,0.779980411323609
|
| 240 |
+
2034-11-01,,,10798042.80687191,0.8236953456017044,11912050.28445178,0.8126271642489349,13777404.544169478,0.7965005382853044
|
| 241 |
+
2034-12-01,,,12267859.003784373,0.7400237080013994,13544674.754166495,0.7299965698884179,15684851.288724562,0.7153888362089266
|
| 242 |
+
2035-01-01,,,13704628.53408369,0.8007209428483025,15143470.12294745,0.7897812809631244,17557721.722671345,0.7738464175861138
|
| 243 |
+
2035-02-01,,,14317681.989912786,0.830234809485518,15833946.762887662,0.8187985200364047,18380734.786731742,0.8021426170140633
|
| 244 |
+
2035-03-01,,,10305608.600497134,0.8115144821291641,11406395.979788747,0.8002447759478898,13257238.350104874,0.7838338064301797
|
| 245 |
+
2035-04-01,,,8925175.981556546,0.8379274140785434,9886667.30012962,0.8261966596483755,11504969.504358165,0.809116725582231
|
| 246 |
+
2035-05-01,,,7259955.529604882,0.8542542001257947,8048694.138800859,0.842198804572316,9377604.400801545,0.8246486755832353
|
| 247 |
+
2035-06-01,,,4915435.157221382,0.8736780262439964,5453957.716070767,0.8612502742010122,6362227.322069967,0.8431606297932387
|
| 248 |
+
2035-07-01,,,6246891.734295842,0.8466627163987902,6937006.574153998,0.8345240521891067,8102153.254672223,0.8168576972888034
|
| 249 |
+
2035-08-01,,,5454009.429782601,0.868056333831907,6061531.174370815,0.8555133583973582,7088292.370985903,0.8372611580158135
|
| 250 |
+
2035-09-01,,,6248905.178560451,0.853940660262113,6950702.892246123,0.8415056576589068,8138023.439484744,0.8234131343533991
|
| 251 |
+
2035-10-01,,,10522212.191781363,0.8058270654175639,11713594.283708742,0.7940021156662961,13731289.413629506,0.7767996314287491
|
| 252 |
+
2035-11-01,,,10852033.020906268,0.8231276002983546,12090731.038718555,0.8109562705568076,14190726.680494564,0.7932523888938039
|
| 253 |
+
2035-12-01,,,12329198.298803294,0.7395136347239082,13747844.87547899,0.7284955781451399,16155396.8273863,0.7124714623951931
|
| 254 |
+
2036-01-01,,,13773151.67675411,0.8001690330226326,15370622.17479166,0.7881573621248449,18084453.374351487,0.7706906522732516
|
| 255 |
+
2036-02-01,,,14389270.399862347,0.829662556751203,16071455.964330977,0.8171149370324866,18932156.830333695,0.798871459082445
|
| 256 |
+
2036-03-01,,,10357136.643499617,0.8109551326824428,11577491.919485576,0.7985993424611507,13654955.500608021,0.7806373122923674
|
| 257 |
+
2036-04-01,,,8969801.861464329,0.8373498590924294,10034967.309631564,0.8244978648654827,11850118.589488909,0.8058171270590334
|
| 258 |
+
2036-05-01,,,7296255.307252906,0.8536653916390426,8169424.55088287,0.8404671067753593,9658932.532825591,0.8212857373740995
|
| 259 |
+
2036-06-01,,,4940012.333007488,0.8730758295717818,5535767.081811828,0.8594794034821687,6553094.141732066,0.8397221993654383
|
| 260 |
+
2036-07-01,,,6278126.192967321,0.8460791404646494,7041061.672766307,0.8328081349319968,8345217.85231239,0.8135265308867031
|
| 261 |
+
2036-08-01,,,5481279.476931513,0.8674580120018663,6152454.141986377,0.8537542837110009,7300941.14211548,0.8338467857835105
|
| 262 |
+
2036-09-01,,,6280149.704453253,0.8533520678877694,7054963.435629814,0.8397753850848033,8382164.142669286,0.8200552347127273
|
| 263 |
+
2036-10-01,,,10574823.25274027,0.8052716361145503,11889298.197964372,0.7923695181049916,14143228.096038392,0.7736318228349538
|
| 264 |
+
2036-11-01,,,10906293.186010798,0.8225602463226129,12272092.004299333,0.8092888124940235,14616448.480909402,0.790017485537884
|
| 265 |
+
2036-12-01,,,12390844.290297309,0.739003913022651,13954062.548611175,0.7269976726851494,16640058.732207887,0.7095659857058465
|
| 266 |
+
2037-01-01,,,13842017.43513788,0.7996175036097126,15601181.507413534,0.7865367823279646,18626986.975582033,0.7675477562513539
|
| 267 |
+
2037-02-01,,,14461216.751861656,0.8290906984513159,16312527.80379594,0.8154348157492012,19500121.535243705,0.795613641015816
|
| 268 |
+
2037-03-01,,,10408922.326717114,0.81039616877635,11751154.298277859,0.7969572922534294,14064604.165626261,0.7774538535387004
|
| 269 |
+
2037-04-01,,,9014650.870771648,0.8367727021954056,10185491.819276035,0.8228025630811164,12205622.147173576,0.8025309843822789
|
| 270 |
+
2037-05-01,,,7332736.583789169,0.8530769889980377,8291965.919146113,0.8387389696308805,9948700.508810358,0.817936513312252
|
| 271 |
+
2037-06-01,,,4964712.394672525,0.8724740479733367,5618803.588039004,0.857712173961705,6749686.965984029,0.8362977909441083
|
| 272 |
+
2037-07-01,,,6309516.823932158,0.8454959667696345,7146677.597857802,0.8310957458800063,8595574.387881761,0.8102089490656571
|
| 273 |
+
2037-08-01,,,5508685.874316171,0.8668601025747984,6244740.954116172,0.8519988259684608,7519969.376378945,0.8304463374477471
|
| 274 |
+
2037-09-01,,,6311550.452975518,0.8527638812102141,7160787.88716426,0.8380486702326869,8633629.066949366,0.8167110286719341
|
| 275 |
+
2037-10-01,,,10627697.36900397,0.804716589650143,12067637.670933835,0.7907402774299536,14567524.938919544,0.7704769326449283
|
| 276 |
+
2037-11-01,,,10960824.65194085,0.8219932834047505,12456173.38436382,0.8076247829963697,15054941.935336683,0.7867957741998745
|
| 277 |
+
2037-12-01,,,12452798.511748794,0.7384945426552981,14163373.486840341,0.7255028471625455,17139260.494174127,0.7066723576241111
|
| 278 |
+
2038-01-01,,,13911227.522313565,0.7990663543473367,15835199.230024736,0.7849195347068708,19185796.584849495,0.7644176770391262
|
| 279 |
+
2038-02-01,,,14533522.835620964,0.828519234313986,16557215.720852874,0.813758149068688,20085125.181301016,0.7923691084138693
|
| 280 |
+
2038-03-01,,,10460966.938350698,0.8098375901451457,11927421.612752026,0.7953186183681527,14486542.290595049,0.774283377010552
|
| 281 |
+
2038-04-01,,,9059724.125125507,0.8361959431130827,10338274.196565175,0.8211107471131022,12571790.811588787,0.7992582426786853
|
| 282 |
+
2038-05-01,,,7369400.266708115,0.8524889919230445,8416345.407933304,0.837014385817598,10247161.52407467,0.8146009474710533
|
| 283 |
+
2038-06-01,,,4989535.956645887,0.8718726811625657,5703085.641859589,0.8559485781527244,6952177.574963549,0.8328873473471513
|
| 284 |
+
2038-07-01,,,6341064.408051818,0.8449131950364955,7253877.761825668,0.8293868777785716,8853441.619518213,0.806904896427399
|
| 285 |
+
2038-08-01,,,5536229.30368775,0.8662626052664474,6338412.068427914,0.850246977732713,7745568.457670312,0.8270597562265198
|
| 286 |
+
2038-09-01,,,6343108.205240396,0.8521760999498139,7268199.705471723,0.8363255057873025,8892637.938957848,0.8133804603881725
|
| 287 |
+
2038-10-01,,,10680835.855848989,0.8041619257604643,12248652.235997843,0.7891143867388766,15004550.68708713,0.7673349081770942
|
| 288 |
+
2038-11-01,,,11015628.775200553,0.8214267112752245,12643015.985129276,0.8059641750141573,15506590.193396783,0.7835872010823927
|
| 289 |
+
2038-12-01,,,12515062.504307535,0.7379855233796875,14375824.089142943,0.7240110952444753,17653438.308999352,0.7037905298310654
|
| 290 |
+
2039-01-01,,,13980783.659925131,0.79851558497348,16072727.218475105,0.7833056124100682,19761370.48239498,0.7613003623692933
|
| 291 |
+
2039-02-01,,,14606190.449799066,0.8279481640675307,16805573.956665665,0.8120849298877216,20687678.936740045,0.7891378070981433
|
| 292 |
+
2039-03-01,,,10513271.773042452,0.8092793965232729,12106332.936943304,0.7936833138630534,14921138.5593129,0.7711258297660772
|
| 293 |
+
2039-04-01,,,9105022.745751131,0.8356195815712605,10493348.30951365,0.8194224097940356,12948944.53593645,0.7959988472987435
|
| 294 |
+
2039-05-01,,,7406247.2680416545,0.8519014001345192,8542590.589052303,0.8352933480292848,10554576.36979691,0.811278984151933
|
| 295 |
+
2039-06-01,,,5014483.636429116,0.8712717288535691,5788631.926487482,0.8541886085837248,7160742.902212455,0.8294908116256592
|
| 296 |
+
2039-07-01,,,6372769.730092076,0.8443308249881737,7362685.928253052,0.8276815233880449,9119044.868103761,0.8036143177995786
|
| 297 |
+
2039-08-01,,,5563910.4502061885,0.865665519792754,6433488.249454332,0.8484987315820238,7977935.511400423,0.8236869855693842
|
| 298 |
+
2039-09-01,,,6374823.746266597,0.8515887238271282,7377222.701053799,0.8346058844484361,9159417.077126583,0.8100634742463234
|
| 299 |
+
2039-10-01,,,10734240.035128232,0.8036076441818185,12432382.019537808,0.787491839143649,15454687.207699744,0.7642056969647104
|
| 300 |
+
2039-11-01,,,11070706.919076556,0.8208605296646776,12832661.224906215,0.804306981512195,15971787.899198689,0.7803917126074416
|
| 301 |
+
2039-12-01,,,12577637.816829072,0.737476854953823,14591461.450480087,0.7225224106111083,18183041.45826933,0.7009204542048321
|
| 302 |
+
2040-01-01,,,14050687.578224756,0.7979651952262982,16313818.12675223,0.7816950086001482,20354211.59686683,0.7581957601877278
|
| 303 |
+
2040-02-01,,,14679221.402048063,0.8273774874404543,17057657.56601565,0.8104151511176811,21308309.30484225,0.7859196831111165
|
| 304 |
+
2040-03-01,,,10565838.131907662,0.8087215876453576,12287927.930997454,0.7920513718101366,15368772.716092288,0.7679811590793295
|
| 305 |
+
2040-04-01,,,9150547.859479887,0.8350436172959277,10650748.534156354,0.8177375439712473,13337412.872014543,0.7927527438158076
|
| 306 |
+
2040-05-01,,,7443278.504381861,0.8513142133531123,8670729.447888087,0.8335758489747365,10871213.660890818,0.8079705678834608
|
| 307 |
+
2040-06-01,,,5039556.054611262,0.8706711907606444,5875461.405384794,0.8524322577985669,7375565.189278829,0.8261081270629631
|
| 308 |
+
2040-07-01,,,6404633.578742536,0.8437488563478016,7473126.217176848,0.8259796754836649,9392616.214146875,0.8003371582348395
|
| 309 |
+
2040-08-01,,,5591730.002457219,0.8650688458698541,6529990.573196146,0.8467540801099199,8217273.576742435,0.8203279691565095
|
| 310 |
+
2040-09-01,,,6406697.864997929,0.8510017525629099,7487881.0415696055,0.8328897989308841,9434199.58944038,0.8067600148580671
|
| 311 |
+
2040-10-01,,,10787911.235303873,0.8030537446506913,12618867.749830876,0.7858726277703219,15918327.823930738,0.7610892467549959
|
| 312 |
+
2040-11-01,,,11126060.453671938,0.8202947383039385,13025151.143279808,0.8026531954697549,16450941.536174648,0.7772092554155171
|
| 313 |
+
2040-12-01,,,12640526.005913217,0.7369685371358758,14810333.372237286,0.7210367869556077,18728532.70201741,0.6980620828197772
|
| 314 |
+
2041-01-01,,,14120941.01611588,0.7974151848441277,16558525.398653511,0.7800877164537623,20964837.944772836,0.7551038186525802
|
| 315 |
+
2041-02-01,,,14752617.5090583,0.8268072041614478,17313522.429505885,0.8087488056845228,21947558.58398752,0.7827146827153092
|
| 316 |
+
2041-03-01,,,10618667.3225672,0.808164163246209,12472246.849962413,0.7904227852956538,15829835.897575058,0.7648493124393797
|
| 317 |
+
2041-04-01,,,9196300.598777285,0.8344680500132623,10810509.762168698,0.8160561425067763,13737535.258174978,0.7895198780251848
|
| 318 |
+
2041-05-01,,,7480494.89690377,0.8507274312996662,8800790.389606407,0.8318618813777406,11197350.070717543,0.8046756434204211
|
| 319 |
+
2041-06-01,,,5064753.834884317,0.8700710665982877,5963593.326465566,0.850679518356442,7596832.144957194,0.8227392371736865
|
| 320 |
+
2041-07-01,,,6436656.746636247,0.8431672888387022,7585223.1104345,0.8242813268555257,9674394.70057128,0.7970733630099026
|
| 321 |
+
2041-08-01,,,5619688.652469505,0.8644725832140804,6627940.431794087,0.8450130159251582,8463791.784044709,0.8169826508977394
|
| 322 |
+
2041-09-01,,,6438731.354322918,0.8504151858781033,7600199.257193149,0.8311772419644222,9717225.577123592,0.80347002706096
|
| 323 |
+
2041-10-01,,,10841850.79148039,0.8025002269037503,12808150.766078334,0.7842567457590793,16395877.658648659,0.7579855055082586
|
| 324 |
+
2041-11-01,,,11181690.755940296,0.8197293369240207,13220528.410429003,0.8010028098805462,16944469.78225989,0.7740397763647175
|
| 325 |
+
2041-12-01,,,12703728.63594278,0.7364605696841843,15032488.372820843,0.7195542179841052,19290388.683077935,0.6952153679457088
|
| 326 |
+
2042-01-01,,,14191545.721196456,0.7968655535654848,16806903.279633313,0.7784837291615911,21593783.08311602,0.7520244861334134
|
| 327 |
+
2042-02-01,,,14826380.596603591,0.8262373139593906,17573225.26594847,0.8070858865287466,22605985.341507144,0.7795227523923827
|
| 328 |
+
2042-03-01,,,10671760.659180034,0.8076071230608192,12659330.552711848,0.7887975474200722,16304730.97450231,0.7617302375494397
|
| 329 |
+
2042-04-01,,,9242282.101771172,0.8338928794496303,10972667.408601228,0.8143781982773383,14149661.315920228,0.7863001959432295
|
| 330 |
+
2042-05-01,,,7517897.371388288,0.8501410536952151,8932802.245450502,0.8301514379770458,11533270.57283907,0.8013941557428887
|
| 331 |
+
2042-06-01,,,5090077.604058738,0.86947135608119,6053047.226362549,0.8489303828318412,7824737.109305911,0.8193840857028009
|
| 332 |
+
2042-07-01,,,6468840.030369428,0.8425861221843893,7699001.457091016,0.8225864703085458,9964626.541588418,0.7938228776246508
|
| 333 |
+
2042-08-01,,,5647787.095731852,0.8638767315419599,6727359.538270999,0.8432755316516913,8717705.53756605,0.8136509749316536
|
| 334 |
+
2042-09-01,,,6470925.011094531,0.8498290234938459,7714202.246051045,0.8294682062937757,10008742.3444373,0.800193455917512
|
| 335 |
+
2042-10-01,,,10896060.04543779,0.8019470906778452,13000273.027569508,0.7826441862642118,16887753.98840812,0.7548944213970253
|
| 336 |
+
2042-11-01,,,11237599.209719995,0.8191643252561245,13418836.336585438,0.7993558177526833,17452803.875727687,0.7708832225298529
|
| 337 |
+
2042-12-01,,,12767247.279122492,0.7359529523572523,15257975.698413154,0.7180746974156729,19869100.343570273,0.692380262047079
|
| 338 |
+
2043-01-01,,,14262503.449802438,0.7963163011290667,17059006.82882781,0.7768830399283165,22241596.5756095,0.7489577112103407
|
| 339 |
+
2043-02-01,,,14900512.499586606,0.8256678165633475,17836823.644937694,0.8054263866053692,23284164.90175236,0.7763438388422491
|
| 340 |
+
2043-03-01,,,10725119.462475933,0.8070504668243622,12849220.511002524,0.7871756512980447,16793872.90373738,0.7586238823259897
|
| 341 |
+
2043-04-01,,,9288493.512280026,0.8333181053315871,11137257.419730244,0.8127037041742952,14574151.155397836,0.7830936438064444
|
| 342 |
+
2043-05-01,,,7555486.858245228,0.8495550802609865,9066794.27913226,0.8284445115263305,11879268.690024242,0.7981260500553122
|
| 343 |
+
2043-06-01,,,5115527.992079031,0.8688720589242394,6143842.934757985,0.8471848438145233,8059479.222585089,0.8160426166246882
|
| 344 |
+
2043-07-01,,,6501184.230521274,0.842005356108567,7814486.478947381,0.8208950986624381,10263565.337836072,0.7905856478012204
|
| 345 |
+
2043-08-01,,,5676026.031210511,0.8632812905702157,6828269.931345062,0.841541619928639,8979236.703693032,0.8103328856246365
|
| 346 |
+
2043-09-01,,,6503279.636150003,0.8492432651314666,7829915.279741811,0.8277626846785867,10309004.61477042,0.7969302467142685
|
| 347 |
+
2043-10-01,,,10950540.345664978,0.8013943357100058,13195277.122983051,0.7810349424540846,17394386.608060364,0.7518159428051762
|
| 348 |
+
2043-11-01,,,11293787.205768595,0.8185997030316341,13620118.881634219,0.7977122121086578,17976387.991999518,0.7677395412015663
|
| 349 |
+
2043-12-01,,,12831083.515518103,0.735445684913751,15486845.33388935,0.7165982189822983,20465173.35387738,0.6895567177821922
|
| 350 |
+
2044-01-01,,,14333815.967051448,0.7957674272737497,17314891.931260224,0.7752856419725932,22908844.472877786,0.7459034426731663
|
| 351 |
+
2044-02-01,,,14975015.062084539,0.8250987117025711,18104375.99961176,0.803770298883892,23982689.848804932,0.773177888982179
|
| 352 |
+
2044-03-01,,,10778745.059788313,0.8064941942721954,13041958.81866756,0.7855570900583826,17297689.0908495,0.7555301948979066
|
| 353 |
+
2044-04-01,,,9334935.979841424,0.8327437273858761,11304316.281026198,0.8110326531036259,15011375.69005977,0.7799001680705794
|
| 354 |
+
2044-05-01,,,7593264.292536453,0.8489695107183991,9202796.193319242,0.8267410947941739,12235646.750724971,0.7948712717855969
|
| 355 |
+
2044-06-01,,,5141105.632039425,0.8682731748425211,6236000.578779355,0.8454428939094846,8301263.599262641,0.8127147741422037
|
| 356 |
+
2044-07-01,,,6533690.15167388,0.8414249903351305,7931703.77613159,0.8192072047516792,10571472.297971154,0.7873616194830948
|
| 357 |
+
2044-08-01,,,5704406.161366562,0.8626862600157656,6930693.980315238,0.8398112734102566,9248613.804803824,0.8070283275699485
|
| 358 |
+
2044-09-01,,,6535796.034330754,0.8486579105124868,7947364.008937935,0.8260606698933857,10618274.753213532,0.7936803449608995
|
| 359 |
+
2044-10-01,,,11005293.047393303,0.8008419617374442,13393206.279827796,0.7794290075111103,17916218.206302173,0.748750018327084
|
| 360 |
+
2044-11-01,,,11350256.141797436,0.8180354699821196,13824420.664858729,0.7960719859853077,18515679.631759502,0.7646086798854486
|
| 361 |
+
2044-12-01,,,12895238.933095692,0.7349387671125175,15719148.01389769,0.7151247764288567,21079128.554493703,0.6867446880024122
|
| 362 |
+
2045-01-01,,,14405485.046886703,0.795218931738591,17574615.310229126,0.7736915285270181,23596109.80706412,0.742861629520532
|
| 363 |
+
2045-02-01,,,15049890.13739496,0.8245299991064995,18375941.639605936,0.8021176163482724,24702170.544269077,0.770024849945915
|
| 364 |
+
2045-03-01,,,10832638.785087254,0.8059383051398578,13237588.200947573,0.7839418568440251,17816619.763574988,0.7524491236056
|
| 365 |
+
2045-04-01,,,9381610.65974063,0.8321697453394289,11473881.025241591,0.8093650379858954,15461716.960761564,0.7767197154097402
|
| 366 |
+
2045-05-01,,,7631230.613999136,0.8483843447890643,9340838.13621903,0.8250411805640231,12602716.15324672,0.7916297665841949
|
| 367 |
+
2045-06-01,,,5166811.160199623,0.8676747035513164,6329540.587461045,0.8437045257369259,8550301.50724052,0.809400502685745
|
| 368 |
+
2045-07-01,,,6566358.602432248,0.8408450245881649,8050679.3327735625,0.8175227814254794,10888616.46691029,0.7841507388342001
|
| 369 |
+
2045-08-01,,,5732928.192173394,0.8620916395957234,7034654.390019966,0.838084484765903,9526072.21894794,0.8037372455867987
|
| 370 |
+
2045-09-01,,,6568475.014502406,0.8480729593586203,8066574.469072005,0.8243621547275596,10936822.995809937,0.7904436963892859
|
| 371 |
+
2045-10-01,,,11060319.512630269,0.800289968497553,13594104.37402521,0.7778263746317201,18453704.75249124,0.7456965967667538
|
| 372 |
+
2045-11-01,,,11407007.422506422,0.8174716258393356,14031786.97483161,0.7944351324337883,19071150.02071229,0.7614905863011651
|
| 373 |
+
2045-12-01,,,12959715.12776117,0.7344321987125549,15954935.234106155,0.7136543635130848,21711502.411128514,0.683944125751377
|
model/revenue/capture_factor_history_forecast/capture_factor_monthly_historical.csv
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
month,p_market_eur_mwh,wind_mwh,price_x_wind,p_wind_capture_eur_mwh,capture_factor
|
| 2 |
+
2015-01-01,31.05307098765432,7830853.25,193848426.705,24.754445079787445,0.7971657646881044
|
| 3 |
+
2015-02-01,36.71691964285714,5325677.75,169937033.715,31.908996693425546,0.8690542944179981
|
| 4 |
+
2015-03-01,31.34314939434724,7010958.25,181407454.6275,25.87484451608309,0.8255342879088481
|
| 5 |
+
2015-04-01,29.724375,5157796.5,133846308.9275,25.950288835067454,0.8730305964403778
|
| 6 |
+
2015-05-01,25.357916666666668,5105062.25,117917513.8575,23.098153966193067,0.9108853171899531
|
| 7 |
+
2015-06-01,30.06438888888889,3871212.5,108847568.965,28.117177490256605,0.9352319647730498
|
| 8 |
+
2015-07-01,34.99568548387097,5401805.25,159520997.85,29.531053132654122,0.8438483980050792
|
| 9 |
+
2015-08-01,31.605094086021502,3553163.75,105496375.725,29.690828553848664,0.9394317407515805
|
| 10 |
+
2015-09-01,31.881319444444443,5328808.5,149441333.1175,28.044042700633735,0.8796387097310245
|
| 11 |
+
2015-10-01,39.38145161290323,3438960.5,126051994.9375,36.654097927993064,0.9307452220979952
|
| 12 |
+
2015-11-01,32.389375,9763092.0,264461081.3275,27.087840750399565,0.8363187233591128
|
| 13 |
+
2015-12-01,27.780604838709678,10359892.25,247403719.2625,23.880916257840422,0.8596254975904842
|
| 14 |
+
2016-01-01,29.035524193548387,8406655.5,205866880.8525,24.488559196044132,0.843399934260027
|
| 15 |
+
2016-02-01,21.989554597701147,9366679.75,174598047.8475,18.640334943393363,0.8476904277698321
|
| 16 |
+
2016-03-01,24.30504710632571,5710792.5,122859575.4525,21.513577222863553,0.885148550782457
|
| 17 |
+
2016-04-01,24.21348611111111,5587231.75,129803828.425,23.232225587385024,0.9594746283445817
|
| 18 |
+
2016-05-01,22.53751009421265,5706867.75,108069163.365,18.936686129619876,0.840229734804759
|
| 19 |
+
2016-06-01,27.596571018651364,2902409.5,77164302.4125,26.586290601825826,0.9633910888369888
|
| 20 |
+
2016-07-01,27.188306451612902,4302145.75,103319912.6825,24.01590245576873,0.8833173371246897
|
| 21 |
+
2016-08-01,27.182567204301076,4262079.75,108755321.68,25.516960746687108,0.9387251967374729
|
| 22 |
+
2016-09-01,30.493861111111112,3729333.5,103678159.8375,27.80072091635141,0.9116825453835887
|
| 23 |
+
2016-10-01,37.17476388888889,4488192.0,152182293.42,33.907260077109,0.9121042484211579
|
| 24 |
+
2016-11-01,38.222541666666665,7267011.75,240768630.505,33.13172439895945,0.8668111264786234
|
| 25 |
+
2016-12-01,37.477889784946235,8416867.75,209774365.61,24.92309156336691,0.6650078674754464
|
| 26 |
+
2017-01-01,52.372956989247314,7186927.25,299615871.055,41.68900847785818,0.796002572213315
|
| 27 |
+
2017-02-01,39.70160714285714,8439755.75,278465181.54,32.99445976739315,0.8310610612983536
|
| 28 |
+
2017-03-01,31.701386271870795,8511720.0,247227272.4325,29.04551282613855,0.9162221669754281
|
| 29 |
+
2017-04-01,28.86991666666667,7421613.0,183933767.205,24.783529834417397,0.8584551912833392
|
| 30 |
+
2017-05-01,30.460510752688172,4963043.75,131569519.505,26.509844791313796,0.8703020447211074
|
| 31 |
+
2017-06-01,30.00161111111111,6153125.0,158199329.8875,25.710404044692737,0.85696744583063
|
| 32 |
+
2017-07-01,33.009112903225805,5011439.25,148281318.315,29.58856945437381,0.8963757838970061
|
| 33 |
+
2017-08-01,30.848387096774193,4804535.25,131183684.21,27.304136068103567,0.8851074120163239
|
| 34 |
+
2017-09-01,34.34861111111111,5904335.5,167116781.355,28.30407949463576,0.8240239875515648
|
| 35 |
+
2017-10-01,28.401478494623657,11014475.5,222444843.28,20.19568188063063,0.7110785406630726
|
| 36 |
+
2017-11-01,40.366625,9256318.75,290753712.135,31.41137637843338,0.7781521585823284
|
| 37 |
+
2017-12-01,30.765725806451613,13454183.0,305012827.27,22.67048302152572,0.7368746365402401
|
| 38 |
+
2018-01-01,29.46159946236559,13144978.0,296746631.88,22.57490517519314,0.7662484585750495
|
| 39 |
+
2018-02-01,40.11510416666666,6859993.0,247755443.2125,36.11599067411585,0.9003090338258714
|
| 40 |
+
2018-03-01,37.36347240915209,9588788.75,291951885.8775,30.447212206807663,0.8148924669900246
|
| 41 |
+
2018-04-01,32.056263888888886,8002044.25,235749094.075,29.461108525487095,0.9190437359638375
|
| 42 |
+
2018-05-01,33.54216397849462,6270346.75,177656212.9,28.332757339137586,0.8446908004296617
|
| 43 |
+
2018-06-01,42.42323611111111,5135329.25,194167016.4875,37.810042362424966,0.891257853677082
|
| 44 |
+
2018-07-01,49.54345430107527,4064678.75,191424653.24,47.09465741665316,0.9505727463099205
|
| 45 |
+
2018-08-01,56.189408602150536,5343261.5,281139784.47,52.6157636997553,0.9364000264231565
|
| 46 |
+
2018-09-01,54.832138888888885,6545188.25,316743606.16,48.39335311096667,0.8825727774185559
|
| 47 |
+
2018-10-01,53.12668010752688,8733167.0,382748623.9175,43.82701303175583,0.8249529792385146
|
| 48 |
+
2018-11-01,56.676013888888896,8035869.5,419561038.75,52.21103189269064,0.9212191950381042
|
| 49 |
+
2018-12-01,48.13212365591398,12092006.75,482731044.0375,39.92149971612446,0.8294148831145396
|
| 50 |
+
2019-01-01,49.393373655913976,12551354.25,490622629.265,39.08921854109886,0.7913858813006717
|
| 51 |
+
2019-02-01,42.82078869047619,8914979.0,342723875.3975,38.44359873393981,0.8977788571766797
|
| 52 |
+
2019-03-01,30.626958277254378,13736642.0,339402745.9525,24.707839510740687,0.8067350106096033
|
| 53 |
+
2019-04-01,36.95590277777778,7303645.75,248842402.1525,34.07098463839104,0.9219362017284695
|
| 54 |
+
2019-05-01,37.84356182795699,6428337.75,230898588.0775,35.91886379608788,0.9491406744264954
|
| 55 |
+
2019-06-01,32.517583333333334,5114514.5,124368577.42,24.316790463689173,0.7478043560132084
|
| 56 |
+
2019-07-01,39.68502688172043,4862707.5,177743961.98,36.552468348137324,0.9210644724288692
|
| 57 |
+
2019-08-01,36.84849462365591,4493530.5,137968102.6075,30.70372007211256,0.8332421822301923
|
| 58 |
+
2019-09-01,35.75070833333333,7145538.75,220748243.425,30.893156016402543,0.8641271028355628
|
| 59 |
+
2019-10-01,36.999556451612904,9341217.0,302823141.18,32.41795380409212,0.8761714169867824
|
| 60 |
+
2019-11-01,41.00120833333333,7880445.25,292288457.58,37.09034810945485,0.9046159763857736
|
| 61 |
+
2019-12-01,31.966142473118282,12208935.0,323883913.7725,26.528432969173803,0.8298915951927173
|
| 62 |
+
2020-01-01,35.0349059139785,12670559.0,394734120.9,31.153646883298517,0.8892173696652799
|
| 63 |
+
2020-02-01,21.919008620689652,17239833.25,302821991.81,17.56525062735163,0.801370670148446
|
| 64 |
+
2020-03-01,22.485827725437417,11552708.75,212318996.7,18.37828697101015,0.8173275716339073
|
| 65 |
+
2020-04-01,17.093125,6991474.0,78419784.1275,11.21648798629588,0.6561987925727963
|
| 66 |
+
2020-05-01,17.596505376344084,6132951.75,80061538.61,13.054323900395923,0.7418702532802646
|
| 67 |
+
2020-06-01,26.18488888888889,4983084.0,110775784.4775,22.230366672024797,0.8489769334655407
|
| 68 |
+
2020-07-01,30.062862903225806,5480898.5,119380704.9125,21.781228919400714,0.7245227771392173
|
| 69 |
+
2020-08-01,34.86395161290322,5156488.25,155318356.07,30.120956073156957,0.8639570295298692
|
| 70 |
+
2020-09-01,43.690194444444444,4632294.25,176342595.7925,38.06809029726468,0.8713188572706236
|
| 71 |
+
2020-10-01,34.01510752688172,10816688.5,325974566.6075,30.13626273951589,0.8859669990959038
|
| 72 |
+
2020-11-01,38.78570833333333,8665897.5,278836504.7425,32.17629850139585,0.8295916172231614
|
| 73 |
+
2020-12-01,43.51974462365591,9073761.0,306943039.6375,33.82754291605212,0.7772918524357464
|
| 74 |
+
2021-01-01,52.806223118279576,9223364.5,430476355.135,46.67237808231476,0.8838423830800066
|
| 75 |
+
2021-02-01,48.70494047619048,8487553.25,373428984.98,43.99724796778153,0.9033426083189586
|
| 76 |
+
2021-03-01,47.16483176312248,9086611.25,318634331.8425,35.066354560122726,0.743485203895938
|
| 77 |
+
2021-04-01,53.61313888888889,7735461.0,348349722.7575,45.03283291810275,0.8399588953639053
|
| 78 |
+
2021-05-01,53.34893817204301,8828518.25,381480066.51,43.2099765450448,0.809950076338887
|
| 79 |
+
2021-06-01,74.07995833333334,3361513.75,215409485.995,64.08109620107905,0.8650260832050826
|
| 80 |
+
2021-07-01,81.36924731182796,4704354.75,327201859.7975,69.55297318883106,0.85478206431339
|
| 81 |
+
2021-08-01,82.69688172043011,6191015.5,455769864.25,73.61794914743793,0.8902143299225604
|
| 82 |
+
2021-09-01,128.37230555555556,4465397.5,529195180.915,118.51020674307271,0.9231758067302543
|
| 83 |
+
2021-10-01,139.59403225806452,10167443.25,1139547028.6075,112.07803186976236,0.8028855536070918
|
| 84 |
+
2021-11-01,176.1513611111111,7822972.75,1114973316.6325,142.525527349242,0.8091082944249354
|
| 85 |
+
2021-12-01,221.06038978494624,9782408.0,1621039440.71,165.70965356484825,0.7496126000956357
|
| 86 |
+
2022-01-01,167.72657258064518,12982727.75,1718042438.0675,132.33293273576504,0.7889801281913014
|
| 87 |
+
2022-02-01,128.80267857142857,17728127.25,1963052746.3075,110.73097110736838,0.8596946300768242
|
| 88 |
+
2022-03-01,252.00685060565274,6793504.0,1400309280.6425,206.1247451451416,0.8179331024127248
|
| 89 |
+
2022-04-01,165.73190277777778,9550806.0,1252718775.385,131.16367093887155,0.7914207750015567
|
| 90 |
+
2022-05-01,177.4769489247312,6454706.0,906536203.7325,140.44577765935426,0.7913465861919791
|
| 91 |
+
2022-06-01,218.0332361111111,4412514.75,875988301.9975,198.52359745596317,0.9105198867698973
|
| 92 |
+
2022-07-01,315.0009946236559,5502496.0,1557781197.615,283.1044670664004,0.8987415020852123
|
| 93 |
+
2022-08-01,465.18350806451616,3527019.25,1628417510.9125,461.6979368378837,0.9925071049033212
|
| 94 |
+
2022-09-01,346.11512500000003,6189613.5,1786718900.0125,288.664049865553,0.8340116597492033
|
| 95 |
+
2022-10-01,152.67469086021507,8613400.25,1113456716.235,129.27028628850724,0.8467040971896496
|
| 96 |
+
2022-11-01,173.634375,10118516.25,1405044651.6125,138.85876317216963,0.7997193134836902
|
| 97 |
+
2022-12-01,251.61639784946237,9410138.25,1442851476.595,153.3294663970532,0.6093778772271731
|
| 98 |
+
2023-01-01,117.82931451612903,14692525.75,1320543325.67,89.87857827439915,0.7627862272091563
|
| 99 |
+
2023-02-01,128.31184523809523,10445029.0,1122610522.9875,107.47797090726124,0.837630935069364
|
| 100 |
+
2023-03-01,102.5214535666218,12133716.25,1058594984.825,87.24408606678931,0.8509837017682864
|
| 101 |
+
2023-04-01,100.74399999999999,8382426.5,764732911.3025,91.23049409410271,0.9055675186026237
|
| 102 |
+
2023-05-01,81.71538978494624,6771381.25,558802219.1075,82.52411117857231,1.0098968064125304
|
| 103 |
+
2023-06-01,94.7561111111111,4872287.25,453830157.63,93.14519738753087,0.9829993685400273
|
| 104 |
+
2023-07-01,77.6061559139785,8392192.75,521347177.1025,62.12287927997126,0.8004890662131304
|
| 105 |
+
2023-08-01,94.3218817204301,5778036.5,400009739.9725,69.2293549846042,0.7339691885049526
|
| 106 |
+
2023-09-01,100.72348611111111,5339625.25,472349969.6125,88.46125851481806,0.878258506831602
|
| 107 |
+
2023-10-01,87.49303763440861,11857250.75,838484140.9875,70.71488649993339,0.8082344425554973
|
| 108 |
+
2023-11-01,91.12227777777777,14477253.5,1119854443.9775,77.35268598961122,0.8488888543617532
|
| 109 |
+
2023-12-01,68.51932795698924,16331164.75,759397979.57,46.49992766560022,0.6786395758987744
|
| 110 |
+
2024-01-01,76.57114247311829,15593084.75,1023895370.9975,65.66342628244229,0.8575479503325244
|
| 111 |
+
2024-02-01,61.335847701149426,14148354.0,765264891.5,54.08861635070765,0.8818434631285619
|
| 112 |
+
2024-03-01,64.70199192462988,9393471.75,527184990.815,56.122486429471614,0.8673996697790639
|
| 113 |
+
2024-04-01,62.360819444444445,9724048.5,492075361.94,50.60396006251923,0.81147041545214
|
| 114 |
+
2024-05-01,67.21001344086021,6274470.0,376861146.4975,60.06262624532431,0.8936559177774147
|
| 115 |
+
2024-06-01,72.88772222222222,5693810.5,340882267.415,59.86891685541695,0.8213854820827964
|
| 116 |
+
2024-07-01,67.69702956989246,5548569.25,299086651.03,53.90338257560721,0.7962444278290781
|
| 117 |
+
2024-08-01,82.04717741935484,5204624.75,348505854.545,66.96080337876424,0.8161256180272725
|
| 118 |
+
2024-09-01,78.30997222222223,8986503.75,586459140.7675,65.25998954459904,0.8333547783596332
|
| 119 |
+
2024-10-01,86.10174731182795,8389045.5,585320668.665,69.77202217642042,0.8103438589199886
|
| 120 |
+
2024-11-01,113.90644444444445,10300191.5,938179143.0125,91.0836602418994,0.7996357070589065
|
| 121 |
+
2024-12-01,108.31559139784946,13757540.0,1011699247.44,73.53780163023332,0.678921664750227
|
| 122 |
+
2025-01-01,114.14016129032258,13253343.0,1153437066.3125,87.02989625428845,0.7624826815595828
|
| 123 |
+
2025-02-01,128.52236607142856,7260679.75,843570877.09,116.18345749101522,0.9039940754471033
|
| 124 |
+
2025-03-01,94.72749663526245,6526920.5,523174378.72,80.15638902297033,0.8461786901389727
|
| 125 |
+
2025-04-01,77.93565277777778,5876514.75,455971894.0425,77.5922316952408,0.995593530428029
|
| 126 |
+
2025-05-01,67.33862903225807,7894329.5,517310337.7625,65.52935721298434,0.9731317396080782
|
| 127 |
+
2025-06-01,63.9875,8705267.75,495674921.255,56.93965257472982,0.8898558714550471
|
| 128 |
+
2025-07-01,87.79522849462366,6193497.28,514036009.4487,82.99608221490976,0.9453370489262092
|
| 129 |
+
2025-08-01,76.99025537634408,5483354.49,387579289.3329,70.68288034992608,0.9180756708029313
|
| 130 |
+
2025-09-01,83.51108333333333,9763607.04,646757234.238,66.24162889681395,0.7932076348765756
|
| 131 |
+
2025-10-01,84.51182795698925,13717685.62,809748019.2526,59.02949241466871,0.6984761049626177
|
| 132 |
+
2025-11-01,101.88231944444445,9908591.42,887009557.9371,89.51923844056334,0.8786533220749594
|
| 133 |
+
2025-12-01,93.47024193548387,12331010.68,1032426448.3832,83.72602012726503,0.8957505447033655
|
model/revenue/capture_factor_history_forecast/cf_his.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
# -----------------------------
|
| 5 |
+
# CONFIG
|
| 6 |
+
# -----------------------------
|
| 7 |
+
PRICES_FILE = "../day_ahead_market_prices/prices_hourly_merged.csv"
|
| 8 |
+
WIND_FILE = "../produced_mwh_wind/wind_onshore_hourly_merged.csv"
|
| 9 |
+
|
| 10 |
+
# Column names – ADJUST if needed
|
| 11 |
+
PRICE_DATE_COL = "datetime"
|
| 12 |
+
PRICE_COL = "price_eur_mwh" # day-ahead price €/MWh
|
| 13 |
+
|
| 14 |
+
WIND_DATE_COL = "datetime"
|
| 15 |
+
WIND_COL = "wind_onshore_mwh" # hourly wind generation in MWh
|
| 16 |
+
|
| 17 |
+
OUTPUT_FILE = "capture_factor_monthly_historical.csv"
|
| 18 |
+
|
| 19 |
+
# -----------------------------
|
| 20 |
+
# 1. Load data
|
| 21 |
+
# -----------------------------
|
| 22 |
+
prices = pd.read_csv(PRICES_FILE, parse_dates=[PRICE_DATE_COL])
|
| 23 |
+
wind = pd.read_csv(WIND_FILE, parse_dates=[WIND_DATE_COL])
|
| 24 |
+
|
| 25 |
+
# ensure numeric
|
| 26 |
+
prices[PRICE_COL] = pd.to_numeric(prices[PRICE_COL], errors="coerce")
|
| 27 |
+
wind[WIND_COL] = pd.to_numeric(wind[WIND_COL], errors="coerce")
|
| 28 |
+
|
| 29 |
+
prices = prices.dropna(subset=[PRICE_DATE_COL, PRICE_COL])
|
| 30 |
+
wind = wind.dropna(subset=[WIND_DATE_COL, WIND_COL])
|
| 31 |
+
|
| 32 |
+
# -----------------------------
|
| 33 |
+
# 2. Merge hourly price & wind
|
| 34 |
+
# -----------------------------
|
| 35 |
+
hourly = prices.merge(
|
| 36 |
+
wind,
|
| 37 |
+
left_on=PRICE_DATE_COL,
|
| 38 |
+
right_on=WIND_DATE_COL,
|
| 39 |
+
how="inner",
|
| 40 |
+
suffixes=("_price", "_wind")
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# keep one timestamp column only
|
| 44 |
+
hourly["timestamp"] = hourly[PRICE_DATE_COL]
|
| 45 |
+
hourly = hourly[["timestamp", PRICE_COL, WIND_COL]]
|
| 46 |
+
|
| 47 |
+
# -----------------------------
|
| 48 |
+
# 3. Add month identifier
|
| 49 |
+
# -----------------------------
|
| 50 |
+
hourly["month"] = hourly["timestamp"].dt.to_period("M").dt.to_timestamp()
|
| 51 |
+
|
| 52 |
+
# -----------------------------
|
| 53 |
+
# 4. Monthly aggregation
|
| 54 |
+
# -----------------------------
|
| 55 |
+
# Market price: simple average
|
| 56 |
+
monthly_market = (
|
| 57 |
+
hourly.groupby("month")[PRICE_COL]
|
| 58 |
+
.mean()
|
| 59 |
+
.rename("p_market_eur_mwh")
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
# Wind capture price: wind-weighted average
|
| 63 |
+
hourly["price_x_wind"] = hourly[PRICE_COL] * hourly[WIND_COL]
|
| 64 |
+
|
| 65 |
+
monthly_wind = (
|
| 66 |
+
hourly.groupby("month")
|
| 67 |
+
.agg(
|
| 68 |
+
wind_mwh=(WIND_COL, "sum"),
|
| 69 |
+
price_x_wind=("price_x_wind", "sum")
|
| 70 |
+
)
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
monthly_wind["p_wind_capture_eur_mwh"] = (
|
| 74 |
+
monthly_wind["price_x_wind"] / monthly_wind["wind_mwh"]
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
# -----------------------------
|
| 78 |
+
# 5. Combine & compute CF
|
| 79 |
+
# -----------------------------
|
| 80 |
+
monthly = pd.concat([monthly_market, monthly_wind], axis=1).reset_index()
|
| 81 |
+
|
| 82 |
+
monthly["capture_factor"] = (
|
| 83 |
+
monthly["p_wind_capture_eur_mwh"] / monthly["p_market_eur_mwh"]
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
# -----------------------------
|
| 87 |
+
# 6. Clean up & save
|
| 88 |
+
# -----------------------------
|
| 89 |
+
monthly = monthly.sort_values("month").reset_index(drop=True)
|
| 90 |
+
|
| 91 |
+
monthly.to_csv(OUTPUT_FILE, index=False)
|
| 92 |
+
print(f"Saved historical capture factors to: {OUTPUT_FILE}")
|
| 93 |
+
|
| 94 |
+
# Optional: quick sanity stats
|
| 95 |
+
print("\nCapture factor summary:")
|
| 96 |
+
print(monthly["capture_factor"].describe())
|
model/revenue/capture_factor_history_forecast/reg_cf.py
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Scenario B2: Capture factor (CF) regression + forecast using scaled historical wind.
|
| 3 |
+
|
| 4 |
+
We model:
|
| 5 |
+
z_t = log(CF_t)
|
| 6 |
+
z_t = const + phi*z_{t-1} + season(month) + beta*log(wind_mwh_t) + error
|
| 7 |
+
|
| 8 |
+
Then we forecast CF for 20 years by:
|
| 9 |
+
- building future wind_mwh_t by scaling a repeating monthly wind pattern
|
| 10 |
+
from a recent reference window, with an annual growth rate per scenario
|
| 11 |
+
- recursively forecasting z_t with AR(1) dynamics
|
| 12 |
+
|
| 13 |
+
Inputs (monthly, historical):
|
| 14 |
+
capture_factor_monthly_historical.csv
|
| 15 |
+
columns: month, p_market_eur_mwh, wind_mwh, p_wind_capture_eur_mwh, capture_factor
|
| 16 |
+
|
| 17 |
+
Outputs:
|
| 18 |
+
capture_factor_forecast_b2.csv
|
| 19 |
+
month, wind_mwh_scen_*, cf_scen_*, p_wind_merchant_scen_* (optional)
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
import numpy as np
|
| 23 |
+
import pandas as pd
|
| 24 |
+
import statsmodels.api as sm
|
| 25 |
+
|
| 26 |
+
# -----------------------------
|
| 27 |
+
# CONFIG
|
| 28 |
+
# -----------------------------
|
| 29 |
+
INPUT_FILE = "capture_factor_monthly_historical.csv" # created by your CF history script
|
| 30 |
+
DATE_COL = "month"
|
| 31 |
+
CF_COL = "capture_factor"
|
| 32 |
+
WIND_COL = "wind_mwh"
|
| 33 |
+
|
| 34 |
+
FORECAST_YEARS = 20
|
| 35 |
+
|
| 36 |
+
# Reference window used to build the repeating seasonal wind pattern (monthly averages)
|
| 37 |
+
REF_START = "2020-01-01"
|
| 38 |
+
REF_END = "2024-12-01"
|
| 39 |
+
|
| 40 |
+
# Wind growth scenarios (annual growth of national wind generation proxy)
|
| 41 |
+
WIND_GROWTH_SCEN = {
|
| 42 |
+
"low": 0.005, # +0.5% p.a.
|
| 43 |
+
"base": 0.015, # +1.5% p.a.
|
| 44 |
+
"high": 0.030, # +3.0% p.a.
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
# CF forecast guardrails (applied after exp() back-transform)
|
| 48 |
+
CF_FLOOR = 0.55
|
| 49 |
+
CF_CAP = 1.15
|
| 50 |
+
|
| 51 |
+
OUTPUT_FILE = "capture_factor_forecast_b2.csv"
|
| 52 |
+
|
| 53 |
+
# -----------------------------
|
| 54 |
+
def to_month_start(s: pd.Series) -> pd.Series:
|
| 55 |
+
dt = pd.to_datetime(s)
|
| 56 |
+
return pd.to_datetime(dt.dt.to_period("M").dt.to_timestamp())
|
| 57 |
+
|
| 58 |
+
# -----------------------------
|
| 59 |
+
# 1) Load historical monthly CF
|
| 60 |
+
# -----------------------------
|
| 61 |
+
df = pd.read_csv(INPUT_FILE, parse_dates=[DATE_COL])
|
| 62 |
+
df[DATE_COL] = to_month_start(df[DATE_COL])
|
| 63 |
+
df = df.sort_values(DATE_COL).reset_index(drop=True)
|
| 64 |
+
|
| 65 |
+
# Basic checks
|
| 66 |
+
df[CF_COL] = pd.to_numeric(df[CF_COL], errors="coerce")
|
| 67 |
+
df[WIND_COL] = pd.to_numeric(df[WIND_COL], errors="coerce")
|
| 68 |
+
df = df.dropna(subset=[CF_COL, WIND_COL])
|
| 69 |
+
|
| 70 |
+
# CF must be positive for log
|
| 71 |
+
df = df[df[CF_COL] > 0].copy()
|
| 72 |
+
|
| 73 |
+
# -----------------------------
|
| 74 |
+
# 2) Build regression dataset: z_t = log(CF_t)
|
| 75 |
+
# -----------------------------
|
| 76 |
+
df["z"] = np.log(df[CF_COL].values.astype(float))
|
| 77 |
+
df["z_lag"] = df["z"].shift(1)
|
| 78 |
+
df["month_num"] = df[DATE_COL].dt.month.astype(int)
|
| 79 |
+
|
| 80 |
+
# Seasonality via month dummies
|
| 81 |
+
month_dummies = pd.get_dummies(df["month_num"], prefix="m", drop_first=True).astype(float)
|
| 82 |
+
|
| 83 |
+
# Wind driver in logs (avoid log(0))
|
| 84 |
+
df["log_wind"] = np.log(np.maximum(df[WIND_COL].values.astype(float), 1.0))
|
| 85 |
+
|
| 86 |
+
X = pd.concat([df["z_lag"], df["log_wind"], month_dummies], axis=1)
|
| 87 |
+
X = sm.add_constant(X)
|
| 88 |
+
reg = pd.concat([df["z"], X], axis=1).dropna()
|
| 89 |
+
|
| 90 |
+
model = sm.OLS(reg["z"].astype(float), reg[X.columns].astype(float)).fit()
|
| 91 |
+
print(model.summary())
|
| 92 |
+
|
| 93 |
+
params = model.params
|
| 94 |
+
const = float(params["const"])
|
| 95 |
+
phi = float(params["z_lag"])
|
| 96 |
+
beta_wind = float(params["log_wind"])
|
| 97 |
+
season_params = {k: float(v) for k, v in params.items() if k.startswith("m_")}
|
| 98 |
+
|
| 99 |
+
# stability clamp (optional but sensible)
|
| 100 |
+
phi = max(min(phi, 0.98), 0.0)
|
| 101 |
+
|
| 102 |
+
print("\n--- Fitted ---")
|
| 103 |
+
print(f"phi={phi:.4f}, beta_wind={beta_wind:.4f}, CF bounds [{CF_FLOOR}, {CF_CAP}]")
|
| 104 |
+
|
| 105 |
+
# -----------------------------
|
| 106 |
+
# 3) Build a repeating monthly wind pattern from the reference window
|
| 107 |
+
# -----------------------------
|
| 108 |
+
mask_ref = (df[DATE_COL] >= pd.Timestamp(REF_START)) & (df[DATE_COL] <= pd.Timestamp(REF_END))
|
| 109 |
+
if mask_ref.sum() < 24:
|
| 110 |
+
raise ValueError("Reference window too short/missing. Adjust REF_START/REF_END.")
|
| 111 |
+
|
| 112 |
+
ref = df.loc[mask_ref, [DATE_COL, WIND_COL]].copy()
|
| 113 |
+
ref["m"] = ref[DATE_COL].dt.month
|
| 114 |
+
|
| 115 |
+
# monthly seasonal wind pattern (average MWh for each month-of-year)
|
| 116 |
+
wind_seasonal = ref.groupby("m")[WIND_COL].mean().to_dict()
|
| 117 |
+
|
| 118 |
+
# anchor wind level: mean in ref window
|
| 119 |
+
wind_anchor = float(ref[WIND_COL].mean())
|
| 120 |
+
anchor_date = df.loc[mask_ref, DATE_COL].iloc[-1]
|
| 121 |
+
|
| 122 |
+
print(f"Wind anchor (mean {REF_START}..{REF_END}): {wind_anchor:,.0f} MWh/month (anchor date {anchor_date.date()})")
|
| 123 |
+
|
| 124 |
+
# -----------------------------
|
| 125 |
+
# 4) Forecast horizon dates
|
| 126 |
+
# -----------------------------
|
| 127 |
+
last_date = df[DATE_COL].max()
|
| 128 |
+
future_dates = pd.date_range(last_date + pd.offsets.MonthBegin(1), periods=FORECAST_YEARS * 12, freq="MS")
|
| 129 |
+
|
| 130 |
+
# Starting state: last observed z
|
| 131 |
+
z_prev = float(df["z"].iloc[-1])
|
| 132 |
+
|
| 133 |
+
# -----------------------------
|
| 134 |
+
# 5) Forecast CF under each wind-growth scenario
|
| 135 |
+
# -----------------------------
|
| 136 |
+
out = pd.DataFrame({DATE_COL: pd.concat([df[DATE_COL], pd.Series(future_dates)], ignore_index=True)})
|
| 137 |
+
out["cf_hist"] = pd.concat([df[CF_COL], pd.Series([np.nan] * len(future_dates))], ignore_index=True)
|
| 138 |
+
out["wind_mwh_hist"] = pd.concat([df[WIND_COL], pd.Series([np.nan] * len(future_dates))], ignore_index=True)
|
| 139 |
+
|
| 140 |
+
for scen, g in WIND_GROWTH_SCEN.items():
|
| 141 |
+
# Build future wind series: seasonal shape * growth factor
|
| 142 |
+
wind_future = []
|
| 143 |
+
for d in future_dates:
|
| 144 |
+
months_from_anchor = (d.year - anchor_date.year) * 12 + (d.month - anchor_date.month)
|
| 145 |
+
growth_factor = (1.0 + g) ** (months_from_anchor / 12.0)
|
| 146 |
+
|
| 147 |
+
# seasonal baseline for month-of-year
|
| 148 |
+
base_m = float(wind_seasonal[int(d.month)])
|
| 149 |
+
# rescale so the mean matches wind_anchor
|
| 150 |
+
# (seasonal dict already in MWh, but this keeps growth around the anchor)
|
| 151 |
+
w = base_m * growth_factor
|
| 152 |
+
wind_future.append(w)
|
| 153 |
+
|
| 154 |
+
wind_future = np.array(wind_future, dtype=float)
|
| 155 |
+
log_wind_future = np.log(np.maximum(wind_future, 1.0))
|
| 156 |
+
|
| 157 |
+
# Forecast z_t recursively (deterministic P50 path)
|
| 158 |
+
z_path = np.zeros(len(future_dates), dtype=float)
|
| 159 |
+
z_prev_s = z_prev
|
| 160 |
+
|
| 161 |
+
for i, d in enumerate(future_dates):
|
| 162 |
+
season_effect = season_params.get(f"m_{d.month}", 0.0) # month 1 baseline 0.0
|
| 163 |
+
z_now = const + phi * z_prev_s + beta_wind * log_wind_future[i] + season_effect
|
| 164 |
+
z_path[i] = z_now
|
| 165 |
+
z_prev_s = z_now
|
| 166 |
+
|
| 167 |
+
cf_future = np.exp(z_path)
|
| 168 |
+
|
| 169 |
+
# Apply guardrails
|
| 170 |
+
cf_future = np.clip(cf_future, CF_FLOOR, CF_CAP)
|
| 171 |
+
|
| 172 |
+
# Store
|
| 173 |
+
out[f"wind_mwh_{scen}"] = np.nan
|
| 174 |
+
out[f"cf_{scen}"] = np.nan
|
| 175 |
+
|
| 176 |
+
future_mask = out[DATE_COL].isin(future_dates)
|
| 177 |
+
out.loc[future_mask, f"wind_mwh_{scen}"] = wind_future
|
| 178 |
+
out.loc[future_mask, f"cf_{scen}"] = cf_future
|
| 179 |
+
|
| 180 |
+
# Save
|
| 181 |
+
out.to_csv(OUTPUT_FILE, index=False)
|
| 182 |
+
print(f"\nSaved CF forecast (Scenario B2) to: {OUTPUT_FILE}")
|
model/revenue/curltailment_rate_per_tso/50Hertz1518.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/50Hertz1922.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/Amprion1518.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/Amprion1922.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/Tennet1518.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/Tennet1922.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/TransnetBW1518.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/TransnetBW1922.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/curltailment_rate_per_tso/curltailment_rate_quarterly_by_tso.csv
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
quarter,TenneT_curtailment_rate,TenneT_production_mwh,TenneT_curtailed_mwh,50Hertz_curtailment_rate,50Hertz_production_mwh,50Hertz_curtailed_mwh,Amprion_curtailment_rate,Amprion_production_mwh,Amprion_curtailed_mwh,TransnetBW_curtailment_rate,TransnetBW_production_mwh,TransnetBW_curtailed_mwh
|
| 2 |
+
2015Q1,0.09530035207443505,8194858.75,863240.0,0.029447978426624857,8396098.5,254750.0,0.0045541750385832145,3597806.0,16460.0,0.0007189108500621559,250198.75,180.0
|
| 3 |
+
2015Q2,0.09232223551591376,5428926.0,552190.0,0.03301157413500447,5115625.75,174640.0,0.0043909375926906415,2244743.75,9900.0,0.0010237457834470544,146370.75,150.0
|
| 4 |
+
2015Q3,0.08906269152732005,5464026.75,534220.0,0.049698280341429805,5116318.5,267570.0,0.004713182524425895,2436911.75,11540.0,0.00911726229951419,204322.25,1880.0
|
| 5 |
+
2015Q4,0.1376137133917989,9454346.25,1508660.0,0.056710695709236376,8709226.25,523600.0,0.0006524281568595988,3967195.75,2590.0,0.0022775368439033185,315411.0,720.0
|
| 6 |
+
2016Q1,0.11403908314741337,9088086.75,1169800.0,0.03968417234191625,7965088.75,329150.0,0.002492969903268064,4453424.5,11130.0,0.002325947310452397,437511.0,1020.0
|
| 7 |
+
2016Q2,0.06500282591989906,5783928.75,402110.0,0.02620616497341991,4798336.5,129130.0,0.0009612773559822682,2255243.0,2170.0,0.0017322469861923801,247802.5,430.0
|
| 8 |
+
2016Q3,0.08397410061565538,5023442.75,460510.0,0.018784136594201518,4313682.75,82580.0,0.004142343442756978,1781432.5,7410.0,0.002580140321565849,235811.25,610.0
|
| 9 |
+
2016Q4,0.2693268665746293,7883700.25,2905940.0,0.09684204258521692,7401934.0,793680.0,0.012692774868053544,3131623.25,40260.0,0.007125029600306795,473791.0,3400.0
|
| 10 |
+
2017Q1,0.10103203552398203,9546415.0,1072890.0,0.041128314496888876,7744028.0,332160.0,0.001289273869082042,4415393.25,5700.0,0.0017965299333364555,650085.5,1170.0
|
| 11 |
+
2017Q2,0.13542094040218902,7453511.0,1167460.0,0.028476218172948722,6627914.0,194270.0,0.00029222431572862825,2531561.25,740.0,0.0007084531402526044,366736.75,260.0
|
| 12 |
+
2017Q3,0.04962306812140752,6028640.75,314780.0,0.020139071371826293,5215786.25,107200.0,0.004346506438805504,2636593.75,11510.0,0.0014176682356437237,366279.5,520.0
|
| 13 |
+
2017Q4,0.12889244238320588,13156996.0,1946760.0,0.028161149640748697,11688162.75,338690.0,0.0033190713664527044,5939718.25,19780.0,0.002631969944601278,822307.5,2170.0
|
| 14 |
+
2018Q1,0.1268028912140319,11630541.25,1688950.0,0.027486834090733287,9202966.0,260110.0,0.0031937154148919313,6164270.0,19750.0,0.002292579942596469,896491.0,2060.0
|
| 15 |
+
2018Q2,0.09039803222877749,7801113.5,775290.0,0.02474019609469666,6392749.75,162170.0,0.002022288394415014,3163266.5,6410.0,0.0024771385095120036,479203.0,1190.0
|
| 16 |
+
2018Q3,0.08619250707598622,6527082.25,615650.0,0.018843631395328308,5251611.5,100860.0,0.002359892078568851,2629493.75,6220.0,0.001063332210128814,347592.75,370.0
|
| 17 |
+
2018Q4,0.12072562638072601,11807743.25,1621220.0,0.011933023176121825,10264847.5,123970.0,0.002576862337850747,5898929.25,15240.0,0.00394989642255305,811991.25,3220.0
|
| 18 |
+
2019Q1,0.16309594006510778,13995837.0,2727510.0,0.03772119552742623,12866117.0,504350.0,0.004159575569904906,7141574.75,29830.0,0.002630054861863574,1107323.0,2920.0
|
| 19 |
+
2019Q2,0.0757248899629744,8192464.25,671200.0,0.028003505063692098,6566750.0,189190.0,0.004115823000902675,3460096.25,14300.0,0.0013681578577072531,576628.75,790.0
|
| 20 |
+
2019Q3,0.09242527777578635,7215897.0,734850.0,0.01889591780924663,5820917.5,112110.0,0.005497930961294054,3008144.25,16630.0,0.0013535094869534376,413179.25,560.0
|
| 21 |
+
2019Q4,0.09914484544370618,11869281.5,1306290.0,0.020015040696809004,9827738.25,200720.0,0.004669104478904939,6663814.0,31260.0,0.0007175833586439269,1002647.75,720.0
|
| 22 |
+
2020Q1,0.1263987966246904,16649725.75,2409000.0,0.03622689605066002,14179825.5,533000.0,0.001965673444636316,9139167.0,18000.0,0.0007300217236214406,1368822.25,1000.0
|
| 23 |
+
2020Q2,0.08958656425205197,7652278.25,753000.0,0.026092787961127305,6307885.5,169000.0,0.005638221673873841,3527217.75,20000.0,0.008817720090293454,562040.0,5000.0
|
| 24 |
+
2020Q3,0.10387380167918364,6547943.5,759000.0,0.023614342558073015,5044351.75,122000.0,0.004351101236528583,3203576.25,14000.0,0.016443234431193287,418707.0,7000.0
|
| 25 |
+
2020Q4,0.0909823250777832,11889463.5,1190000.0,0.01652246982319331,9523782.25,160000.0,0.0012697024591160767,6292688.75,8000.0,0.0,776930.25,0.0
|
| 26 |
+
2021Q1,0.1232079070182118,11194037.75,1573000.0,0.029212089188968154,8706889.5,262000.0,0.004553583535321305,5902396.0,27000.0,0.001115655236871736,895334.25,1000.0
|
| 27 |
+
2021Q2,0.12498272369689316,8037269.5,1148000.0,0.04886486485043129,7124044.25,366000.0,0.006656793655483931,4029006.75,27000.0,0.003013372215879492,661708.25,2000.0
|
| 28 |
+
2021Q3,0.09737752558343477,6562671.5,708000.0,0.03304682037784841,5413118.0,185000.0,0.011511429537566408,2919586.25,34000.0,0.0024022408102277806,415278.0,1000.0
|
| 29 |
+
2021Q4,0.08872773855692674,11472073.25,1117000.0,0.034816724980992794,9813527.25,354000.0,0.0021196948398987865,5649192.25,12000.0,0.00129169552798862,773176.25,1000.0
|
| 30 |
+
2022Q1,0.12810022516371697,15416467.75,2265000.0,0.06746653111498681,13366032.75,967000.0,0.006943418185353013,7437106.75,52000.0,0.0008432725298702942,1184856.25,1000.0
|
| 31 |
+
2022Q2,0.1514992349312791,8781887.25,1568000.0,0.07451236551741768,6806484.0,548000.0,0.004101540635169408,4127784.0,17000.0,0.0,595612.0,0.0
|
model/revenue/curltailment_rate_per_tso/curltailmentcalc.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
# -------------------------------------------------
|
| 5 |
+
# CONFIG
|
| 6 |
+
# -------------------------------------------------
|
| 7 |
+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 8 |
+
|
| 9 |
+
PRODUCTION_FILE = "wind_onshore_daily_by_tso.csv"
|
| 10 |
+
CURTAILMENT_FILE = "curtailment.csv"
|
| 11 |
+
|
| 12 |
+
OUTPUT_FILE = "curtailment_rate_quarterly_by_tso.csv"
|
| 13 |
+
|
| 14 |
+
# TSO column names (must match both files)
|
| 15 |
+
TSOS = ["TenneT", "50Hertz", "Amprion", "TransnetBW"]
|
| 16 |
+
|
| 17 |
+
# -------------------------------------------------
|
| 18 |
+
def parse_german_number(x):
|
| 19 |
+
"""
|
| 20 |
+
Convert strings like '863,24' to float 863.24
|
| 21 |
+
"""
|
| 22 |
+
if pd.isna(x):
|
| 23 |
+
return float("nan")
|
| 24 |
+
return float(str(x).replace(".", "").replace(",", "."))
|
| 25 |
+
|
| 26 |
+
def parse_quarter_label(q):
|
| 27 |
+
"""
|
| 28 |
+
'Q1 2015' -> pandas Period('2015Q1')
|
| 29 |
+
"""
|
| 30 |
+
q = q.strip()
|
| 31 |
+
year = int(q[-4:])
|
| 32 |
+
quarter = int(q[1])
|
| 33 |
+
return pd.Period(year=year, quarter=quarter, freq="Q")
|
| 34 |
+
|
| 35 |
+
def main():
|
| 36 |
+
# -----------------------------
|
| 37 |
+
# Load production data (daily)
|
| 38 |
+
# -----------------------------
|
| 39 |
+
prod = pd.read_csv(
|
| 40 |
+
os.path.join(BASE_DIR, PRODUCTION_FILE),
|
| 41 |
+
parse_dates=["date"]
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure numeric
|
| 45 |
+
for tso in TSOS:
|
| 46 |
+
prod[tso] = pd.to_numeric(prod[tso], errors="coerce")
|
| 47 |
+
|
| 48 |
+
# Create quarter index
|
| 49 |
+
prod["quarter"] = prod["date"].dt.to_period("Q")
|
| 50 |
+
|
| 51 |
+
# Aggregate daily → quarterly (MWh)
|
| 52 |
+
prod_q = (
|
| 53 |
+
prod.groupby("quarter")[TSOS]
|
| 54 |
+
.sum()
|
| 55 |
+
.reset_index()
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
# -----------------------------
|
| 59 |
+
# Load curtailment data (quarterly)
|
| 60 |
+
# -----------------------------
|
| 61 |
+
curt = pd.read_csv(os.path.join(BASE_DIR, CURTAILMENT_FILE))
|
| 62 |
+
|
| 63 |
+
# Parse quarter
|
| 64 |
+
curt["quarter"] = curt["Quarter"].apply(parse_quarter_label)
|
| 65 |
+
|
| 66 |
+
# Parse German numbers & convert GWh → MWh
|
| 67 |
+
for tso in TSOS:
|
| 68 |
+
curt[tso] = curt[tso].apply(parse_german_number) * 1_000
|
| 69 |
+
|
| 70 |
+
# Keep only relevant columns
|
| 71 |
+
curt_q = curt[["quarter"] + TSOS]
|
| 72 |
+
|
| 73 |
+
# -----------------------------
|
| 74 |
+
# Merge production + curtailment
|
| 75 |
+
# -----------------------------
|
| 76 |
+
df = prod_q.merge(curt_q, on="quarter", how="inner", suffixes=("_prod", "_curt"))
|
| 77 |
+
|
| 78 |
+
# -----------------------------
|
| 79 |
+
# Compute curtailment rates
|
| 80 |
+
# -----------------------------
|
| 81 |
+
out = pd.DataFrame({"quarter": df["quarter"]})
|
| 82 |
+
|
| 83 |
+
for tso in TSOS:
|
| 84 |
+
prod_col = f"{tso}_prod"
|
| 85 |
+
curt_col = f"{tso}_curt"
|
| 86 |
+
|
| 87 |
+
out[f"{tso}_curtailment_rate"] = (
|
| 88 |
+
df[curt_col] / (df[curt_col] + df[prod_col])
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
out[f"{tso}_production_mwh"] = df[prod_col]
|
| 92 |
+
out[f"{tso}_curtailed_mwh"] = df[curt_col]
|
| 93 |
+
|
| 94 |
+
# Sort and save
|
| 95 |
+
out = out.sort_values("quarter").reset_index(drop=True)
|
| 96 |
+
out.to_csv(os.path.join(BASE_DIR, OUTPUT_FILE), index=False)
|
| 97 |
+
|
| 98 |
+
print(f"Saved: {OUTPUT_FILE}")
|
| 99 |
+
print("\nPreview:")
|
| 100 |
+
print(out.head(5).to_string(index=False))
|
| 101 |
+
|
| 102 |
+
if __name__ == "__main__":
|
| 103 |
+
main()
|
model/revenue/curltailment_rate_per_tso/curtailment.csv
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Quarter,TenneT,50Hertz,Amprion,TransnetBW,GesamtWindOnshore
|
| 2 |
+
Q1 2015,"863,24","254,75","16,46","0,18","969,69"
|
| 3 |
+
Q2 2015,"552,19","174,64","9,90","0,15","588,37"
|
| 4 |
+
Q3 2015,"534,22","267,57","11,54","1,88","733,45"
|
| 5 |
+
Q4 2015,"1508,66","523,60","2,59","0,72","1819,05"
|
| 6 |
+
Q1 2016,"1169,80","329,15","11,13","1,02","1451,41"
|
| 7 |
+
Q2 2016,"402,11","129,13","2,17","0,43","481,78"
|
| 8 |
+
Q3 2016,"460,51","82,58","7,41","0,61","497,90"
|
| 9 |
+
Q4 2016,"2905,94","793,68","40,26","3,4","3498,02"
|
| 10 |
+
Q1 2017,"1072,89","332,16","5,70","1,17","1300,17"
|
| 11 |
+
Q2 2017,"1167,46","194,27","0,74","0,26","1162,75"
|
| 12 |
+
Q3 2017,"314,78","107,20","11,51","0,52","336,05"
|
| 13 |
+
Q4 2017,"1946,76","338,69","19,78","2,17","1654,56"
|
| 14 |
+
Q1 2018,"1688,95","260,11","19,75","2,06","1431,34"
|
| 15 |
+
Q2 2018,"775,29","162,17","6,41","1,19","765,82"
|
| 16 |
+
Q3 2018,"615,65","100,86","6,22","0,37","575,48"
|
| 17 |
+
Q4 2018,"1621,22","123,97","15,24","3,22","1111,99"
|
| 18 |
+
Q1 2019,"2727,51","504,35","29,83","2,92","2520,17"
|
| 19 |
+
Q2 2019,"671,20","189,19","14,30","0,79","730,51"
|
| 20 |
+
Q3 2019,"734,85","112,11","16,63","0,56","700,43"
|
| 21 |
+
Q4 2019,"1306,29","200,72","31,26","0,72","1199,15"
|
| 22 |
+
Q1 2020,"2409,00","533,00","18,00","1,00","2169,00"
|
| 23 |
+
Q2 2020,"753,00","169,00","20,00","5,00","636,00"
|
| 24 |
+
Q3 2020,"759,00","122,00","14,00","7,00","520,00"
|
| 25 |
+
Q4 2020,"1190,00","160,00","8,00","0,00","804,00"
|
| 26 |
+
Q1 2021,"1573,00","262,00","27,00","1,00","1145,00"
|
| 27 |
+
Q2 2021,"1148,00","366,00","27,00","2,00","995,00"
|
| 28 |
+
Q3 2021,"708,00","185,00","34,00","1,00","527,00"
|
| 29 |
+
Q4 2021,"1117,00","354,00","12,00","1,00","741,00"
|
| 30 |
+
Q1 2022,"2265,00","967,00","52,00","1,00","1638,00"
|
| 31 |
+
Q2 2022,"1568,00","548,00","17,00","0,00","1069,00"
|
model/revenue/curltailment_rate_per_tso/curtailment_forecast_quarterly_by_tso_2021_2046.csv
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
quarter,TSO,wind_mwh,load_mwh,S,cr_hat
|
| 2 |
+
2021Q1,50Hertz,10332139.598789917,26458894.51705215,0.3904977810819379,0.037591391757116115
|
| 3 |
+
2021Q2,50Hertz,6250356.920074381,23348612.198897533,0.2676971490566582,0.033994561506153556
|
| 4 |
+
2021Q3,50Hertz,5208241.8405525815,23550796.659246545,0.22114928492271257,0.03263117466462488
|
| 5 |
+
2021Q4,50Hertz,9703123.698236724,25964529.24843711,0.3737068985689693,0.03709958684400646
|
| 6 |
+
2022Q1,50Hertz,10435460.994777817,26591188.98963741,0.39244055611219636,0.037648295633622306
|
| 7 |
+
2022Q2,50Hertz,6312860.489275125,23465355.25989202,0.2690289756688804,0.03403357070479426
|
| 8 |
+
2022Q3,50Hertz,5260324.258958107,23668550.64254278,0.222249530121333,0.0326634008441535
|
| 9 |
+
2022Q4,50Hertz,9800154.935219092,26094351.894679293,0.37556613687030754,0.03715404392990016
|
| 10 |
+
2023Q1,50Hertz,10539815.604725594,26724144.934585594,0.39439299668986894,0.0377054826139917
|
| 11 |
+
2023Q2,50Hertz,6375989.094167876,23582682.03619148,0.27036742828414845,0.034072773979050085
|
| 12 |
+
2023Q3,50Hertz,5312927.501547689,23786893.39575549,0.22335524917666308,0.032695787352933506
|
| 13 |
+
2023Q4,50Hertz,9898156.484571284,26224823.654152684,0.3774346251134435,0.037208771946569456
|
| 14 |
+
2024Q1,50Hertz,10645213.76077285,26857765.65925852,0.3963551509022564,0.03776295410670125
|
| 15 |
+
2024Q2,50Hertz,6439748.985109555,23700595.446372434,0.2717125398676517,0.03411217229447137
|
| 16 |
+
2024Q3,50Hertz,5366056.776563165,23905827.862734266,0.22446646932182057,0.03272833498862286
|
| 17 |
+
2024Q4,50Hertz,9997138.049416997,26355947.77242345,0.37931240931798793,0.037263772241928644
|
| 18 |
+
2025Q1,50Hertz,10751665.89838058,26992054.48755481,0.3983270670758995,0.03782071152723523
|
| 19 |
+
2025Q2,50Hertz,6504146.47496065,23819098.42360429,0.2730643435485854,0.03415176662141216
|
| 20 |
+
2025Q3,50Hertz,5419717.3443287965,24025357.002047934,0.22558321792541178,0.03276104455284799
|
| 21 |
+
2025Q4,50Hertz,10097109.429911166,26487727.511285562,0.38119953573250537,0.03731904617059808
|
| 22 |
+
2026Q1,50Hertz,10859182.557364386,27127014.759992577,0.4003087937777698,0.03787875629812012
|
| 23 |
+
2026Q2,50Hertz,6569187.939710257,23938193.91572231,0.27442287262096643,0.03419155793505415
|
| 24 |
+
2026Q3,50Hertz,5473914.517772085,24145483.78705817,0.2267055224922049,0.03279391685122349
|
| 25 |
+
2026Q4,50Hertz,10198080.524210278,26620166.14884199,0.3830960508356522,0.03737459509393751
|
| 26 |
+
2027Q1,50Hertz,10967774.38293803,27262649.83379254,0.4023003798164651,0.03793708984895966
|
| 27 |
+
2027Q2,50Hertz,6634879.819107359,24057884.88530092,0.2757881605444538,0.034231547215430674
|
| 28 |
+
2027Q3,50Hertz,5528653.662949806,24266211.20599346,0.22783341066380794,0.032826952693372005
|
| 29 |
+
2027Q4,50Hertz,10300061.32945238,26753266.97958619,0.3850020013373222,0.037430420380079626
|
| 30 |
+
2028Q1,50Hertz,11077452.12676741,27398963.0829615,0.4043018742434128,0.03799571361647004
|
| 31 |
+
2028Q2,50Hertz,6701228.617298433,24178174.309727423,0.2771602409451725,0.03427173544745086
|
| 32 |
+
2028Q3,50Hertz,5583940.199579304,24387542.26202342,0.22896691021934934,0.03286015289294414
|
| 33 |
+
2028Q4,50Hertz,10403061.942746906,26887033.31448412,0.3869174341797965,0.03748652340396374
|
| 34 |
+
2029Q1,50Hertz,11188226.648035085,27535957.898376305,0.40631332635407663,0.03805462904451531
|
| 35 |
+
2029Q2,50Hertz,6768240.903471417,24299065.181276057,0.2785391476165416,0.03431212362092389
|
| 36 |
+
2029Q3,50Hertz,5639779.601575096,24509479.973333538,0.23010604907616197,0.032893518267638526
|
| 37 |
+
2029Q4,50Hertz,10507092.562174374,27021468.48105654,0.38884239653889996,0.037542905547369665
|
| 38 |
+
2030Q1,50Hertz,11300108.914515434,27673637.687868185,0.4083347856891715,0.03811383758414288
|
| 39 |
+
2030Q2,50Hertz,6835923.312506132,24420560.507182434,0.27992491452010654,0.03435271273058335
|
| 40 |
+
2030Q3,50Hertz,5696177.397590848,24632027.373200204,0.23125085529047126,0.03292704963922194
|
| 41 |
+
2030Q4,50Hertz,10612163.487796118,27156575.82346182,0.3907769358251632,0.03759956819895174
|
| 42 |
+
2031Q1,50Hertz,11413110.003660588,27812005.87630752,0.4103663020358838,0.03817334069361935
|
| 43 |
+
2031Q2,50Hertz,6904282.545631194,24542663.309718344,0.28131757578637573,0.03439350377611176
|
| 44 |
+
2031Q3,50Hertz,5753139.171566756,24755187.510066204,0.2324013570580856,0.03296074783354955
|
| 45 |
+
2031Q4,50Hertz,10718285.12267408,27292358.70257913,0.3927210996849899,0.03765651275427303
|
| 46 |
+
2032Q1,50Hertz,11527241.103697194,27951065.905689057,0.4124079254290972,0.038233139838466344
|
| 47 |
+
2032Q2,50Hertz,6973325.371087505,24665376.626266934,0.2827171657156612,0.03443449776216519
|
| 48 |
+
2032Q3,50Hertz,5810670.563282425,24878963.44761653,0.23355758271509106,0.032994613680585254
|
| 49 |
+
2032Q4,50Hertz,10825467.97390082,27428820.49609202,0.3946749360018306,0.037713740615839694
|
| 50 |
+
2033Q1,50Hertz,11642513.514734168,28090821.2352175,0.4144597061526251,0.038293236491496664
|
| 51 |
+
2033Q2,50Hertz,7043058.624798381,24788703.509398267,0.28412371877892323,0.034475695698397986
|
| 52 |
+
2033Q3,50Hertz,5868777.268915248,25003358.264854606,0.23471956073854924,0.03302864801442213
|
| 53 |
+
2033Q4,50Hertz,10933722.653639829,27565964.598572478,0.39663849289736225,0.037771253193135554
|
| 54 |
+
2034Q1,50Hertz,11758938.649881508,28231275.341393583,0.4165216947404492,0.03835363213285052
|
| 55 |
+
2034Q2,50Hertz,7113489.211046365,24912647.026945256,0.2855372696186194,0.034517098599487664
|
| 56 |
+
2034Q3,50Hertz,5927465.041604401,25128375.05617888,0.23588731974719876,0.03306285167330297
|
| 57 |
+
2034Q4,50Hertz,11043059.880176226,27703794.421565335,0.39861181873267254,0.037829051902656764
|
| 58 |
+
2035Q1,50Hertz,11876528.036380323,28372431.718100548,0.4185939419779639,0.038414328250032
|
| 59 |
+
2035Q2,50Hertz,7184624.103156828,25037210.262079976,0.2869578530495579,0.034558707485159885
|
| 60 |
+
2035Q3,50Hertz,5986739.692020444,25254016.93145977,0.23706088850215995,0.033097225499640934
|
| 61 |
+
2035Q4,50Hertz,11153490.478977988,27842313.39367316,0.400594962109452,0.037887138167946734
|
| 62 |
+
2036Q1,50Hertz,11995293.316744126,28514293.876691047,0.42067649890322745,0.03847532633794573
|
| 63 |
+
2036Q2,50Hertz,7256470.344188396,25162396.313390374,0.28838550405975466,0.03460052338021355
|
| 64 |
+
2036Q3,50Hertz,6046607.088940649,25380287.016117066,0.2382402959076434,0.033131770340040285
|
| 65 |
+
2036Q4,50Hertz,11265025.383767769,27981524.960641526,0.4025879718711906,0.037945513419631184
|
| 66 |
+
2037Q1,50Hertz,12115246.249911569,28656865.346074495,0.4227694168082188,0.03853662789893366
|
| 67 |
+
2037Q2,50Hertz,7329035.047630281,25288208.294957325,0.28982025781129583,0.03464254731454609
|
| 68 |
+
2037Q3,50Hertz,6107073.159830056,25507188.45119765,0.23942557101166154,0.03316648704531724
|
| 69 |
+
2037Q4,50Hertz,11377675.637605445,28121432.58544473,0.4045908971043806,0.038004179095453366
|
| 70 |
+
2038Q1,50Hertz,12236398.712410685,28800149.67280487,0.42487274724010043,0.038598234442812074
|
| 71 |
+
2038Q2,50Hertz,7402325.398106583,25414649.336432107,0.2912621496412028,0.034684780323178795
|
| 72 |
+
2038Q3,50Hertz,6168143.891428357,25634724.393453635,0.2406167430067445,0.03320137647052094
|
| 73 |
+
2038Q4,50Hertz,11491452.393981501,28262039.74837195,0.4066037871397259,0.03806313664030949
|
| 74 |
+
2039Q1,50Hertz,12358762.699534792,28944150.42116889,0.4269865420024891,0.03866014748690879
|
| 75 |
+
2039Q2,50Hertz,7476348.652087649,25541722.583114266,0.2927112150623033,0.03472722344628231
|
| 76 |
+
2039Q3,50Hertz,6229825.33034264,25762898.015420903,0.24181384123065863,0.03323643947495451
|
| 77 |
+
2039Q4,50Hertz,11606366.917921318,28403349.947113805,0.4086266915533565,0.03812238750628431
|
| 78 |
+
2040Q1,50Hertz,12482350.32653014,29088871.17327473,0.42911085315673037,0.03872236855610051
|
| 79 |
+
2040Q2,50Hertz,7551112.1386085255,25669431.196029834,0.29416748976410584,0.03476987772920226
|
| 80 |
+
2040Q3,50Hertz,6292123.5836460665,25891712.505498003,0.2430168951671296,0.033271676922196215
|
| 81 |
+
2040Q4,50Hertz,11722430.58710053,28545366.696849372,0.41065966016804983,0.03818193315268685
|
| 82 |
+
2041Q1,50Hertz,12607173.82979544,29234315.529141102,0.43124573302318175,0.0387848991828504
|
| 83 |
+
2041Q2,50Hertz,7626623.25999461,25797778.352009982,0.2956310096136785,0.034812744222484995
|
| 84 |
+
2041Q3,50Hertz,6355044.819482528,26021171.06802549,0.24422593444656812,0.033307089680120715
|
| 85 |
+
2041Q4,50Hertz,11839654.892971536,28688093.530333616,0.4127027430544581,0.038241775046086425
|
| 86 |
+
2042Q1,50Hertz,12733245.568093395,29380487.106786806,0.4333912341825011,0.03884774090724581
|
| 87 |
+
2042Q2,50Hertz,7702889.492594557,25926767.243770026,0.29710181065653274,0.03485582398190346
|
| 88 |
+
2042Q3,50Hertz,6418595.267677354,26151276.923365615,0.24544098884679982,0.033342678620920455
|
| 89 |
+
2042Q4,50Hertz,11958051.44190125,28831533.997985277,0.414755990532341,0.038301914660348685
|
| 90 |
+
2043Q1,50Hertz,12860578.023774331,29527389.542320736,0.43554740947694154,0.03891089527703623
|
| 91 |
+
2043Q2,50Hertz,7779918.387520503,26056401.079988874,0.2985799291175105,0.03489911806848322
|
| 92 |
+
2043Q3,50Hertz,6482781.220354126,26282033.307982437,0.24666208829379885,0.033378444621127164
|
| 93 |
+
2043Q4,50Hertz,12077631.956320263,28975691.6679752,0.4168194531718055,0.03836235347667195
|
| 94 |
+
2044Q1,50Hertz,12989183.804012073,29675026.490032334,0.43771431201165273,0.03897436384767137
|
| 95 |
+
2044Q2,50Hertz,7857717.571395707,26186683.085388817,0.30006540140167726,0.034942627548528546
|
| 96 |
+
2044Q3,50Hertz,6547609.032557667,26413443.47452235,0.24788926286242471,0.0334143885616334
|
| 97 |
+
2044Q4,50Hertz,12198408.275883466,29120570.126315072,0.4188931817945509,0.03842309298362369
|
| 98 |
+
2045Q1,50Hertz,13119075.642052194,29823401.622482494,0.43989199515598937,0.03903814818233953
|
| 99 |
+
2045Q2,50Hertz,7936294.747109665,26317616.500815757,0.30155826409521796,0.034986353493648724
|
| 100 |
+
2045Q3,50Hertz,6613085.122883244,26545510.69189496,0.24912254277716317,0.0334505113277143
|
| 101 |
+
2045Q4,50Hertz,12320392.3586423,29266172.976946644,0.4209772274751208,0.03848413467717718
|
| 102 |
+
2046Q1,50Hertz,13250266.398472717,29972518.630594905,0.44208051254482517,0.03910224985200603
|
| 103 |
+
2046Q2,50Hertz,8015657.694580762,26449204.58331983,0.3030585539663385,0.03503029698078443
|
| 104 |
+
2046Q3,50Hertz,6679215.974112077,26678238.24535443,0.2503619584128705,0.03348681380904934
|
| 105 |
+
2046Q4,50Hertz,12443596.282228725,29412503.84183138,0.4230716415421612,0.038545480060748344
|
| 106 |
+
2021Q1,Amprion,6607879.562974096,43397052.420583755,0.15226563082980027,0.0034787359242224973
|
| 107 |
+
2021Q2,Amprion,3478748.138202513,39140322.7988437,0.0888788821717455,0.0040932599068450905
|
| 108 |
+
2021Q3,Amprion,2928110.483509553,39256092.77548496,0.07458996238510342,0.004231788606937147
|
| 109 |
+
2021Q4,Amprion,5919954.583392162,42203211.27664723,0.14027260969754488,0.0035950062688276246
|
| 110 |
+
2022Q1,Amprion,6673958.358603838,43614037.68268667,0.15302317128168985,0.0034713916955730027
|
| 111 |
+
2022Q2,Amprion,3513535.6195845385,39336024.412837915,0.08932106566513728,0.004088973011442471
|
| 112 |
+
2022Q3,Amprion,2957391.588344649,39452373.239362374,0.07496105672532784,0.004228190909047424
|
| 113 |
+
2022Q4,Amprion,5979154.129226084,42414227.33303046,0.14097048337763218,0.0035882404996040243
|
| 114 |
+
2023Q1,Amprion,6740697.942189876,43832107.871100105,0.153784480591549,0.003464010928472514
|
| 115 |
+
2023Q2,Amprion,3548670.975780384,39532704.5349021,0.08976544907640663,0.004084664788202033
|
| 116 |
+
2023Q3,Amprion,2986965.5042280955,39649635.105559185,0.07533399730605086,0.004224575312163224
|
| 117 |
+
2023Q4,Amprion,6038945.670518344,42626298.469695605,0.14167182906607814,0.0035814410698370228
|
| 118 |
+
2024Q1,Amprion,6808104.921611775,44051268.4104556,0.15454957750991494,0.0034565934411376967
|
| 119 |
+
2024Q2,Amprion,3584157.6855381876,39730368.05757661,0.0902120433504186,0.004080335131015123
|
| 120 |
+
2024Q3,Amprion,3016835.1592703764,39847883.28108698,0.07570879331254864,0.00422094172723483
|
| 121 |
+
2024Q4,Amprion,6099335.127223528,42839429.96204408,0.14237666403655616,0.0035746078120612312
|
| 122 |
+
2025Q1,Amprion,6876185.970827892,44271524.75250787,0.15531848088061104,0.0034491390508808104
|
| 123 |
+
2025Q2,Amprion,3619999.2623935696,39929019.89786448,0.09066085948649036,0.004075983933245191
|
| 124 |
+
2025Q3,Amprion,3047003.51086308,40047122.697492406,0.07608545397579516,0.004217290064769473
|
| 125 |
+
2025Q4,Amprion,6160328.478495764,43053627.1118543,0.14308500564867835,0.0035677405579780976
|
| 126 |
+
2026Q1,Amprion,6944947.830536172,44492882.3762704,0.15609120964121115,0.0034416475741052346
|
| 127 |
+
2026Q2,Amprion,3656199.255017505,40128664.99735381,0.09111190853866194,0.00407161108772516
|
| 128 |
+
2026Q3,Amprion,3077473.545971711,40247358.310979865,0.07646398857268967,0.004213620234829164
|
| 129 |
+
2026Q4,Amprion,6221931.763280721,43268895.24741357,0.14379687134842303,0.0035608391384517636
|
| 130 |
+
2027Q1,Amprion,7014397.308841534,44715346.788151756,0.15686778282350572,0.0034341188263009303
|
| 131 |
+
2027Q2,Amprion,3692761.24756768,40329308.32234057,0.09156520161596873,0.004067216486754781
|
| 132 |
+
2027Q3,Amprion,3108248.2814314286,40448595.10253476,0.07684440642628515,0.004209932147028458
|
| 133 |
+
2027Q4,Amprion,6284151.080913529,43485239.72365063,0.14451227866856448,0.0035539033835048986
|
| 134 |
+
2028Q1,Amprion,7084541.281929949,44938923.52209251,0.15764821955397096,0.0034265526220398843
|
| 135 |
+
2028Q2,Amprion,3729688.860043357,40530954.86395227,0.09202074988271486,0.004062800022097985
|
| 136 |
+
2028Q3,Amprion,3139330.7642457425,40650838.078047425,0.07722671690601793,0.004206225710532224
|
| 137 |
+
2028Q4,Amprion,6346992.591722664,43702665.922268875,0.1452312452291046,0.0035469331223145183
|
| 138 |
+
2029Q1,Amprion,7155386.694749249,45163618.13970296,0.1584325390542395,0.0034189487749715676
|
| 139 |
+
2029Q2,Amprion,3766985.748643791,40733609.63827203,0.09247856455874827,0.0040583615849802065
|
| 140 |
+
2029Q3,Amprion,3170724.0718881995,40854092.26843766,0.07761092942793842,0.004202500834053425
|
| 141 |
+
2029Q4,Amprion,6410462.51763989,43921179.25188022,0.1459537887377071,0.0035399281832077696
|
| 142 |
+
2030Q1,Amprion,7226940.561696741,45389436.23040148,0.159220760641574,0.0034113070978183356
|
| 143 |
+
2030Q2,Amprion,3804655.606130229,40937277.68646338,0.0929386569197371,0.004053901066085722
|
| 144 |
+
2030Q3,Amprion,3202431.312607082,41058362.72977985,0.0779970534549431,0.0041987574258508485
|
| 145 |
+
2030Q4,Amprion,6474567.14281629,44140785.14813961,0.14667992699013357,0.003532888393657705
|
| 146 |
+
2031Q1,Amprion,7299209.967313708,45616383.41155348,0.16001290372934304,0.0034036274023708096
|
| 147 |
+
2031Q2,Amprion,3842702.162191531,41141964.074895695,0.09340103829744724,0.004049418355554953
|
| 148 |
+
2031Q3,Amprion,3234455.625733153,41263654.54342874,0.0783850984970075,0.004194995393726867
|
| 149 |
+
2031Q4,Amprion,6539312.814244453,44361489.073880315,0.14740967787068146,0.003525813580279029
|
| 150 |
+
2032Q1,Amprion,7372202.066986845,45844465.32861124,0.160808987827499,0.0033959094994832455
|
| 151 |
+
2032Q2,Amprion,3881129.183813446,41347673.89527017,0.0938657200800216,0.004044913342981734
|
| 152 |
+
2032Q3,Amprion,3266800.1819904847,41469972.816145875,0.0787750741114205,0.0041912146450251535
|
| 153 |
+
2032Q4,Amprion,6604705.942386897,44583296.51924971,0.14814305935262517,0.0035187035688238437
|
| 154 |
+
2033Q1,Amprion,7445924.087656715,46073687.6552543,0.16160903254305872,0.003388153199068874
|
| 155 |
+
2033Q2,Amprion,3919940.4756515813,41554412.26474652,0.09433271371226054,0.0040403859174106445
|
| 156 |
+
2033Q3,Amprion,3299468.1838103896,41677322.6802266,0.07916698990301961,0.004187415086628409
|
| 157 |
+
2033Q4,Amprion,6670753.001810767,44806213.001845956,0.14888008949865816,0.003511558184177338
|
| 158 |
+
2034Q1,Amprion,7520383.328533281,46304056.09353056,0.16241305758058638,0.0033803583100952307
|
| 159 |
+
2034Q2,Amprion,3959139.8804080975,41762184.32607024,0.09480203069590365,0.004035835967334225
|
| 160 |
+
2034Q3,Amprion,3332462.865648493,41885709.29362773,0.07956085552442767,0.004183596624956057
|
| 161 |
+
2034Q4,Amprion,6737460.531828873,45030244.06685517,0.14962078646133806,0.0035043772503534874
|
| 162 |
+
2035Q1,Amprion,7595587.161818613,46535576.3739982,0.16322108274267888,0.0033725246405794315
|
| 163 |
+
2035Q2,Amprion,3998731.279212178,41970995.24770059,0.09527368258991313,0.004031263380690257
|
| 164 |
+
2035Q3,Amprion,3365787.494304978,42095137.84009587,0.07995668067629048,0.004179759165961951
|
| 165 |
+
2035Q4,Amprion,6804835.137147162,45255395.28718945,0.1503651684835338,0.0034971605904907145
|
| 166 |
+
2036Q1,Amprion,7671543.033436799,46768254.2558682,0.1640331279304534,0.003364651997583453
|
| 167 |
+
2036Q2,Amprion,4038718.5920042996,42180850.22393908,0.09574768101075848,0.004026668044859006
|
| 168 |
+
2036Q3,Amprion,3399445.369248028,42305613.52929634,0.08035447510751584,0.004175902615132052
|
| 169 |
+
2036Q4,Amprion,6872883.488518634,45481672.26362539,0.15111325389887476,0.0034899080268475276
|
| 170 |
+
2037Q1,Amprion,7748258.463771168,47002095.527147524,0.1648492131440378,0.003356740187209384
|
| 171 |
+
2037Q2,Amprion,4079105.777924343,42391754.47505878,0.09622403763270256,0.004022049846660443
|
| 172 |
+
2037Q3,Amprion,3433439.8229405084,42517141.59694282,0.08075424861551343,0.004172026877482107
|
| 173 |
+
2037Q4,Amprion,6941612.32340382,45709080.62494351,0.15186506113220252,0.0034826193807981597
|
| 174 |
+
2038Q1,Amprion,7825741.04840888,47237106.00478326,0.16566935848306288,0.0033487890145946463
|
| 175 |
+
2038Q2,Amprion,4119896.8357035867,42603713.24743407,0.09670276418808915,0.0040174086723514316
|
| 176 |
+
2038Q3,Amprion,3467774.2211699137,42729727.30492753,0.0811560110464364,0.004168131857555296
|
| 177 |
+
2038Q4,Amprion,7011028.446637859,45937626.02806822,0.15262060870002445,0.0034752944728281415
|
| 178 |
+
2039Q1,Amprion,7903998.458892969,47473291.53480717,0.16649358414715776,0.0033407982839072023
|
| 179 |
+
2039Q2,Amprion,4161095.804060622,42816731.81367124,0.09718387246763188,0.004012744407622976
|
| 180 |
+
2039Q3,Amprion,3502451.9633816127,42943375.94145217,0.08155977229542365,0.004164217459419892
|
| 181 |
+
2039Q4,Amprion,7081138.731104238,46167314.15820856,0.15337991521096989,0.0034679331225299197
|
| 182 |
+
2040Q1,Amprion,7983038.443481899,47710657.992481194,0.16732191043644712,0.0033327677983407133
|
| 183 |
+
2040Q2,Amprion,4202706.762101228,43030815.472739585,0.0976673743207047,0.004008056937597364
|
| 184 |
+
2040Q3,Amprion,3537476.4830154288,43158092.82115942,0.08196554230684368,0.0041602835866669
|
| 185 |
+
2040Q4,Amprion,7151950.11841528,46398150.7289996,0.15414299936624834,0.003460535148598367
|
| 186 |
+
2041Q1,Amprion,8062868.827916718,47949211.282443605,0.16815435775205134,0.003324697360109718
|
| 187 |
+
2041Q2,Amprion,4244733.829722241,43245969.550103284,0.09815328165563357,0.004003346146825352
|
| 188 |
+
2041Q3,Amprion,3572851.247845583,43373883.28526521,0.08237333107453944,0.004156330142407676
|
| 189 |
+
2041Q4,Amprion,7223469.619599434,46630141.482644595,0.1549098799601103,0.003453100368826366
|
| 190 |
+
2042Q1,Amprion,8143497.516195885,48188957.33885582,0.16899094659658892,0.0033165867704447356
|
| 191 |
+
2042Q2,Amprion,4287181.168019463,43462199.39785379,0.09864160643998998,0.003998611919283336
|
| 192 |
+
2042Q3,Amprion,3608579.7603240395,43590752.70169153,0.08278314864207448,0.004152357029271539
|
| 193 |
+
2042Q4,Amprion,7295704.315795427,46863292.19005781,0.15568057588030987,0.0034456286001002707
|
| 194 |
+
2043Q1,Amprion,8224932.491357844,48429902.12555009,0.16983169757468142,0.003308435829587387
|
| 195 |
+
2043Q2,Amprion,4330052.979699658,43679510.39484306,0.09913236070088546,0.003993854138370459
|
| 196 |
+
2043Q3,Amprion,3644665.5579272793,43808706.465199985,0.08319500510298031,0.004148364149403384
|
| 197 |
+
2043Q4,Amprion,7368661.358953382,47097608.651008084,0.15645510610857016,0.0034381196583954388
|
| 198 |
+
2044Q1,Amprion,8307181.816271422,48672051.63617783,0.17067663139346098,0.0033002443367854788
|
| 199 |
+
2044Q2,Amprion,4373353.509496654,43897907.946817264,0.099625556525268,0.0039890726869057785
|
| 200 |
+
2044Q3,Amprion,3681112.213506552,44027749.99752598,0.08360891060100509,0.004144351404461254
|
| 201 |
+
2044Q4,Amprion,7442347.972542915,47333096.69426312,0.15723348972105058,0.0034305733587716783
|
| 202 |
+
2045Q1,Amprion,8390253.634434137,48915411.89435872,0.1715257688630802,0.003292012090288038
|
| 203 |
+
2045Q2,Amprion,4417087.044591621,44117397.486551344,0.10012120606021958,0.003984267447125354
|
| 204 |
+
2045Q3,Amprion,3717923.335641618,44247888.74751361,0.08402487533036335,0.0041403186956139384
|
| 205 |
+
2045Q4,Amprion,7516771.452268345,47569762.177734435,0.15801574588881706,0.003422989515368697
|
| 206 |
+
2046Q1,Amprion,8474156.170778478,49159988.95383051,0.17237913089722487,0.0032837388873403622
|
| 207 |
+
2046Q2,Amprion,4461257.915037537,44337984.4739841,0.1006193215132555,0.003979438300679355
|
| 208 |
+
2046Q3,Amprion,3755102.5689980336,44469128.191251166,0.08444290953598704,0.0041362659235385305
|
| 209 |
+
2046Q4,Amprion,7591939.166791029,47807610.988623105,0.15880189387831367,0.0034153679414015183
|
| 210 |
+
2021Q1,TenneT,12447538.18763111,36111271.20442925,0.34469952932879167,0.12715710853226286
|
| 211 |
+
2021Q2,TenneT,7708988.706875039,32033876.410622682,0.2406511346943537,0.11115882842036676
|
| 212 |
+
2021Q3,TenneT,6477958.469000448,32595113.862966057,0.19874016996027677,0.10471467946514934
|
| 213 |
+
2021Q4,TenneT,11609727.10634837,35641542.32964574,0.3257358225121389,0.12424128561468112
|
| 214 |
+
2022Q1,TenneT,12572013.569507422,36291827.56045139,0.3464144523602783,0.12742079178393106
|
| 215 |
+
2022Q2,TenneT,7786078.59394379,32194045.792675793,0.24184840402119132,0.11134291823864242
|
| 216 |
+
2022Q3,TenneT,6542738.053690452,32758089.432280883,0.19972892702475578,0.10486670884086176
|
| 217 |
+
2022Q4,TenneT,11725824.377411852,35819750.041293964,0.32735639874354255,0.12449046228466978
|
| 218 |
+
2023Q1,TenneT,12697733.705202496,36473286.69825365,0.34813790734714534,0.1276857868925727
|
| 219 |
+
2023Q2,TenneT,7863939.379883228,32355016.02163917,0.24305162991184404,0.11152792392666078
|
| 220 |
+
2023Q3,TenneT,6608165.434227357,32921879.879442286,0.2007226032786103,0.10501949458162746
|
| 221 |
+
2023Q4,TenneT,11843082.621185971,35998848.79150043,0.32898503754326175,0.1247408786395838
|
| 222 |
+
2024Q1,TenneT,12824711.04225452,36655653.13174491,0.3498699367369322,0.12795210038483948
|
| 223 |
+
2024Q2,TenneT,7942578.77368206,32516791.10174736,0.2442608420009577,0.11171385004098766
|
| 224 |
+
2024Q3,TenneT,6674247.08856963,33086489.278839495,0.20172122319541932,0.10517304045045665
|
| 225 |
+
2024Q4,TenneT,11961513.447397832,36178843.03545793,0.3306217790235765,0.12499254084700978
|
| 226 |
+
2025Q1,TenneT,12952958.152677067,36838931.39740363,0.35161058318835975,0.12821973881985382
|
| 227 |
+
2025Q2,TenneT,8022004.561418881,32679375.05725609,0.24547607007061428,0.11190070116085847
|
| 228 |
+
2025Q3,TenneT,6740989.559455327,33251921.725233685,0.20272481137052095,0.10532735022908105
|
| 229 |
+
2025Q4,TenneT,12081128.58187181,36359737.250635214,0.33226666349633066,0.12524545510521903
|
| 230 |
+
2026Q1,TenneT,13082487.734203838,37023126.05439064,0.3533598895723815,0.12848870878937074
|
| 231 |
+
2026Q2,TenneT,8102224.607033068,32842771.932542372,0.24669734405106505,0.11208848188829082
|
| 232 |
+
2026Q3,TenneT,6808399.45504988,33418181.333859853,0.20373339252161807,0.10548242771804683
|
| 233 |
+
2026Q4,TenneT,12201939.867690528,36541535.93688839,0.33391973147392434,0.12549962764331982
|
| 234 |
+
2027Q1,TenneT,13213312.611545878,37208241.684662595,0.35511789897323914,0.12875901691793995
|
| 235 |
+
2027Q2,TenneT,8183246.853103399,33006985.79220508,0.2479246940214684,0.11227719684819795
|
| 236 |
+
2027Q3,TenneT,6876483.44960038,33585272.24052915,0.20474699148938738,0.10563827673680848
|
| 237 |
+
2027Q4,TenneT,12323959.266367434,36724243.61657282,0.3355810236703122,0.1257550647214112
|
| 238 |
+
2028Q1,TenneT,13345445.737661336,37394282.893085904,0.35688465468952396,0.12903066986306924
|
| 239 |
+
2028Q2,TenneT,8265079.321634434,33172020.7211661,0.24915815021063,0.11246685068850265
|
| 240 |
+
2028Q3,TenneT,6945248.284096383,33753198.601731785,0.20576563323809083,0.10579490112382267
|
| 241 |
+
2028Q4,TenneT,12447198.85903111,36907864.83465568,0.33725058100200533,0.12601177263073687
|
| 242 |
+
2029Q1,TenneT,13478900.19503795,37581254.307551324,0.3586602002352431,0.12930367431538822
|
| 243 |
+
2029Q2,TenneT,8347730.114850778,33337880.82477193,0.2503977429977476,0.11265744808025163
|
| 244 |
+
2029Q3,TenneT,7014700.766937346,33921964.59474044,0.20678934285619077,0.10595230473664291
|
| 245 |
+
2029Q4,TenneT,12571670.847621419,37092404.15882896,0.33892844458907995,0.12626975769384025
|
| 246 |
+
2030Q1,TenneT,13613689.196988327,37769160.57908908,0.36044457934089097,0.12957803699881323
|
| 247 |
+
2030Q2,TenneT,8431207.415999286,33504570.228895783,0.2516435029131593,0.11284899371773072
|
| 248 |
+
2030Q3,TenneT,7084847.774606721,34091574.41771414,0.2078181455569679,0.10611049145201448
|
| 249 |
+
2030Q4,TenneT,12697387.556097634,37277866.1796231,0.3406146557561899,0.12652902626472026
|
| 250 |
+
2031Q1,TenneT,13749826.088958211,37958006.38198452,0.3622378359545274,0.12985376467071305
|
| 251 |
+
2031Q2,TenneT,8515519.490159279,33672093.08004026,0.2528954606390954,0.11304149231858034
|
| 252 |
+
2031Q3,TenneT,7155696.252352787,34262032.289802715,0.20885206667914183,0.10626946516597
|
| 253 |
+
2031Q4,TenneT,12824361.43165861,37464255.51052121,0.34230925603358386,0.12678958472898774
|
| 254 |
+
2032Q1,TenneT,13887324.349847792,38147796.41389444,0.36404001424285837,0.130130864122075
|
| 255 |
+
2032Q2,TenneT,8600674.685060872,33840453.54544046,0.25415364701043425,0.11323494862391179
|
| 256 |
+
2032Q3,TenneT,7227253.2148763165,34433342.451251715,0.2098911316874959,0.1064292297939253
|
| 257 |
+
2032Q4,TenneT,12952605.045975195,37651576.788073815,0.34401228715812904,0.1270514395040227
|
| 258 |
+
2033Q1,TenneT,14026197.593346274,38338535.39596391,0.3658511585923254,0.1304093421776726
|
| 259 |
+
2033Q2,TenneT,8686681.431911482,34009655.813167654,0.25541809301546137,0.11342936739842402
|
| 260 |
+
2033Q3,TenneT,7299525.747025079,34605509.163507976,0.2109353661735033,0.10658978927077588
|
| 261 |
+
2033Q4,TenneT,13082131.096434949,37839834.672014184,0.3457237910743387,0.1273145970391325
|
| 262 |
+
2034Q1,TenneT,14166459.569279734,38530228.072943725,0.36767131361019767,0.13068920569623338
|
| 263 |
+
2034Q2,TenneT,8773548.246230597,34179704.092233494,0.25668882979663277,0.11362475343052086
|
| 264 |
+
2034Q3,TenneT,7372521.004495329,34778536.70932551,0.21198479585595859,0.10675114755099388
|
| 265 |
+
2034Q4,TenneT,13212952.407399297,38029033.84537424,0.34744380993540513,0.1275790638157105
|
| 266 |
+
2035Q1,TenneT,14308124.16497253,38722879.21330844,0.3695005241256713,0.1309704615706079
|
| 267 |
+
2035Q2,TenneT,8861283.728692902,34350602.61269465,0.25796588865134246,0.11382111153242916
|
| 268 |
+
2035Q3,TenneT,7446246.214540282,34952429.39287213,0.21303944658161011,0.10691330860872542
|
| 269 |
+
2035Q4,TenneT,13345081.931473289,38219179.01460112,0.3491723861042379,0.12784484634739585
|
| 270 |
+
2036Q1,TenneT,14451205.406622257,38916493.60937498,0.3713388351909732,0.1312531167279395
|
| 271 |
+
2036Q2,TenneT,8949896.56597983,34522355.62575812,0.25924930103269245,0.11401844654031709
|
| 272 |
+
2036Q3,TenneT,7520708.676685685,35127191.53983649,0.21409934432579728,0.10707627643788845
|
| 273 |
+
2036Q4,TenneT,13478532.750788022,38410274.909674115,0.35090956215450786,0.12811195118023386
|
| 274 |
+
2037Q1,TenneT,14595717.46068848,39111076.077421844,0.37318629208247067,0.13153717812983495
|
| 275 |
+
2037Q2,TenneT,9039395.53163963,34694967.403886914,0.260539098550268,0.11421676331441338
|
| 276 |
+
2037Q3,TenneT,7595915.763452543,35302827.497535676,0.2151645151930898,0.10724005505227119
|
| 277 |
+
2037Q4,TenneT,13613318.078295903,38602326.28422248,0.3526553808716945,0.12838038489283723
|
| 278 |
+
2038Q1,TenneT,14741674.635295365,39306631.45780895,0.3750429403017865,0.13182265277253585
|
| 279 |
+
2038Q2,TenneT,9129789.486956026,34868442.24090634,0.26183531297091617,0.1144160667391271
|
| 280 |
+
2038Q3,TenneT,7671874.9210870685,35479341.63502334,0.21623498541793112,0.10740464848563097
|
| 281 |
+
2038Q4,TenneT,13749451.259078862,38795337.915643595,0.35440988525414074,0.12865015409654806
|
| 282 |
+
2039Q1,TenneT,14889091.381648319,39503164.61509799,0.3769088255769198,0.13210954768709096
|
| 283 |
+
2039Q2,TenneT,9221087.381825587,35042784.45211087,0.2631379762195277,0.11461636172316778
|
| 284 |
+
2039Q3,TenneT,7748593.670297938,35656738.34319846,0.21731078136528395,0.10757006079179351
|
| 285 |
+
2039Q4,TenneT,13886945.771669652,38989314.6052218,0.35617311851411176,0.12892126543560078
|
| 286 |
+
2040Q1,TenneT,15037982.295464803,39700680.43817347,0.37878399386337225,0.13239786993952946
|
| 287 |
+
2040Q2,TenneT,9313298.255643843,35217998.374371424,0.26444712037982393,0.11481765319966633
|
| 288 |
+
2040Q3,TenneT,7826079.607000918,35835022.03491445,0.21839192953128045,0.1077362960447529
|
| 289 |
+
2040Q4,TenneT,14025815.229386348,39184261.17824791,0.35794512407885853,0.12919372558728556
|
| 290 |
+
2041Q1,TenneT,15188362.11841945,39899183.84036434,0.3806684913452796,0.1326876266310348
|
| 291 |
+
2041Q2,TenneT,9406431.23820028,35394088.36624327,0.26576277769514645,0.11501994612629673
|
| 292 |
+
2041Q3,TenneT,7904340.403070928,36014197.145089015,0.2194784565438739,0.1079033583387718
|
| 293 |
+
2041Q4,TenneT,14166073.381680213,39380182.484139144,0.35972594559168874,0.1294675412621131
|
| 294 |
+
2042Q1,TenneT,15340245.739603644,40098679.75956616,0.3825623644365496,0.13297882489811977
|
| 295 |
+
2042Q2,TenneT,9500495.550582284,35571058.80807449,0.2670849805692517,0.11522324548539793
|
| 296 |
+
2042Q3,TenneT,7983383.807101638,36194268.130814455,0.22057038916349525,0.10807125178848233
|
| 297 |
+
2042Q4,TenneT,14307734.115497014,39577083.396559834,0.36151562691304046,0.12974271920397956
|
| 298 |
+
2043Q1,TenneT,15493648.196999682,40299173.15836398,0.3844656597820052,0.13327147191280217
|
| 299 |
+
2043Q2,TenneT,9595500.506088106,35748914.102114856,0.26841376156710867,0.11542755628409664
|
| 300 |
+
2043Q3,TenneT,8063217.645172653,36375239.47146852,0.22166775428371163,0.10823998052898744
|
| 301 |
+
2043Q4,TenneT,14450811.456651984,39774968.81354263,0.3633142121215631,0.1300192661903329
|
| 302 |
+
2044Q1,TenneT,15648584.678969678,40500669.024155796,0.3863784242585326,0.1335655748827815
|
| 303 |
+
2044Q2,TenneT,9691455.511148987,35927658.67262542,0.2697491534157013,0.11563288355443069
|
| 304 |
+
2044Q3,TenneT,8143849.82162438,36557115.668825865,0.2227705789318893,0.10840954871596271
|
| 305 |
+
2044Q4,TenneT,14595319.571218504,39973843.657610334,0.36512174551520277,0.13029718903233975
|
| 306 |
+
2045Q1,TenneT,15805070.525759377,40703172.36927657,0.38830070497623687,0.13386114105161648
|
| 307 |
+
2045Q2,TenneT,9788370.066260478,36107296.96598855,0.2710911890048342,0.11583923235347285
|
| 308 |
+
2045Q3,TenneT,8225288.319840624,36739901.247169994,0.2238788902698589,0.10857996052575876
|
| 309 |
+
2045Q4,TenneT,14741272.76693069,40173712.87589838,0.3669382716122934,0.1305764945750531
|
| 310 |
+
2046Q1,TenneT,15963121.23101697,40906688.231122956,0.39023254927960116,0.13415817769890334
|
| 311 |
+
2046Q2,TenneT,9886253.766923083,36287833.45081849,0.2724399013879429,0.11604660776345552
|
| 312 |
+
2046Q3,TenneT,8307541.20303903,36923600.75340583,0.22499271559458464,0.10875122015550406
|
| 313 |
+
2046Q4,TenneT,14888685.494599998,40374581.440277874,0.3687638351526531,0.13085718969758095
|
| 314 |
+
2021Q1,TransnetBW,982592.6868155334,14907943.888683865,0.06591067783407661,0.001822947089878152
|
| 315 |
+
2021Q2,TransnetBW,527448.8774056936,13084479.565202389,0.04031103222541776,0.002714510254756039
|
| 316 |
+
2021Q3,TransnetBW,399061.20892765094,13197586.721116466,0.030237437901365943,0.0030653450192111263
|
| 317 |
+
2021Q4,TransnetBW,829085.9884025174,14552773.808496533,0.056970993936459144,0.0021342909651258547
|
| 318 |
+
2022Q1,TransnetBW,992418.6136836888,14982483.608127283,0.06623859165414665,0.0018115267800934733
|
| 319 |
+
2022Q2,TransnetBW,532723.3661797505,13149901.963028401,0.040511584624549186,0.0027075255826075686
|
| 320 |
+
2022Q3,TransnetBW,403051.8210169275,13263574.654722048,0.030387872915800605,0.003060105793651985
|
| 321 |
+
2022Q4,TransnetBW,837376.8482865426,14625537.677539015,0.05725443171723755,0.0021244196298448974
|
| 322 |
+
2023Q1,TransnetBW,1002342.7998205257,15057396.026167918,0.06656813688625683,0.0018000496528471806
|
| 323 |
+
2023Q2,TransnetBW,538050.5998415481,13215651.47284354,0.040713134796810636,0.0027005061608464213
|
| 324 |
+
2023Q3,TransnetBW,407082.33922709676,13329892.527995655,0.030539056363142903,0.0030548405022940463
|
| 325 |
+
2023Q4,TransnetBW,845750.616769408,14698665.365926707,0.05753927963622879,0.002114499183443138
|
| 326 |
+
2024Q1,TransnetBW,1012366.227818731,15132683.006298756,0.06689932164688499,0.001788515425465334
|
| 327 |
+
2024Q2,TransnetBW,543431.1058399635,13281729.730207758,0.040915687706247504,0.002693451816588952
|
| 328 |
+
2024Q3,TransnetBW,411153.1626193677,13396541.990635633,0.030690991966939633,0.003049549015456711
|
| 329 |
+
2024Q4,TransnetBW,854208.1229371021,14772158.69275634,0.057825544709045856,0.0021045293815866485
|
| 330 |
+
2025Q1,TransnetBW,1022489.8900969182,15208346.421330249,0.06723215409288939,0.001776923813867657
|
| 331 |
+
2025Q2,TransnetBW,548865.4168983632,13348138.378858794,0.04111924834160198,0.002686362376091392
|
| 332 |
+
2025Q3,TransnetBW,415264.6942455614,13463524.70058881,0.03084368346926272,0.0030442312028142147
|
| 333 |
+
2025Q4,TransnetBW,862750.2041664731,14846019.48622012,0.0581132339862053,0.00209450997872589
|
| 334 |
+
2026Q1,TransnetBW,1032714.7889978875,15284388.153436897,0.06756664242170976,0.001765274532560538
|
| 335 |
+
2026Q2,TransnetBW,554354.0710673467,13414879.070753088,0.04132382171643581,0.002679237664745586
|
| 336 |
+
2026Q3,TransnetBW,419417.34118801705,13530842.324091753,0.030997134630801344,0.0030388869333924026
|
| 337 |
+
2026Q4,TransnetBW,871377.7062081379,14920249.583651219,0.05840235455330085,0.00208444072808971
|
| 338 |
+
2027Q1,TransnetBW,1043041.9368878665,15360810.094204081,0.06790279487156901,0.001753567294630002
|
| 339 |
+
2027Q2,TransnetBW,559897.6117780203,13481953.466106853,0.04152941286925391,0.002672077507074676
|
| 340 |
+
2027Q3,TransnetBW,423611.51459989726,13598496.53571221,0.031151349230954594,0.0030335160755655087
|
| 341 |
+
2027Q4,TransnetBW,880091.4832702193,14994850.831569472,0.05869291353117798,0.0020743213816792165
|
| 342 |
+
2028Q1,TransnetBW,1053472.356256745,15437614.1446751,0.06824061972167633,0.001741801811734639
|
| 343 |
+
2028Q2,TransnetBW,565496.5878958005,13549363.233437384,0.04173602686362832,0.0026648817267287857
|
| 344 |
+
2028Q3,TransnetBW,427847.6297458962,13666489.01839077,0.03130633106792452,0.0030281184970529056
|
| 345 |
+
2028Q4,TransnetBW,888892.3981029216,15069825.085727317,0.05898491807610923,0.002064151690261709
|
| 346 |
+
2029Q1,TransnetBW,1064007.0798193126,15514802.215398472,0.06858012529243096,0.0017299777940985028
|
| 347 |
+
2029Q2,TransnetBW,571151.5537747585,13617110.04960457,0.04194366878832299,0.0026576501464806827
|
| 348 |
+
2029Q3,TransnetBW,432126.10604335513,13734821.463482723,0.031462083958809714,0.003022694064915867
|
| 349 |
+
2029Q4,TransnetBW,897781.3220839506,15145174.211155953,0.059278375379970466,0.002053931403364514
|
| 350 |
+
2030Q1,TransnetBW,1074647.1506175057,15592376.226475464,0.06892131994562713,0.001718094950503974
|
| 351 |
+
2030Q2,TransnetBW,576863.0693125061,13685195.59985259,0.042152343757419136,0.002650382588221388
|
| 352 |
+
2030Q3,TransnetBW,436447.3671037887,13803495.570800135,0.03161861173969932,0.0030172426455542627
|
| 353 |
+
2030Q4,TransnetBW,906759.1353047902,15220900.082211731,0.05957329267041809,0.002043660269268825
|
| 354 |
+
2031Q1,TransnetBW,1085393.6221236805,15670338.10760784,0.06926421208466009,0.001706152988284599
|
| 355 |
+
2031Q2,TransnetBW,582631.7000056312,13753621.577851852,0.04236205691044112,0.0026430788729558292
|
| 356 |
+
2031Q3,TransnetBW,440811.8407748266,13872513.048654133,0.03177591826576748,0.0030117641047032982
|
| 357 |
+
2031Q4,TransnetBW,915826.7266578382,15297004.58262279,0.05986967721106694,0.0020333380350035027
|
| 358 |
+
2032Q1,TransnetBW,1096247.5583449174,15748689.798145877,0.06960881015473304,0.0016941516133178666
|
| 359 |
+
2032Q2,TransnetBW,588458.0170056875,13822389.685741112,0.04257281341248312,0.0026357388207984035
|
| 360 |
+
2032Q3,TransnetBW,445219.9591825749,13941875.613897402,0.03193400741136832,0.0030062583074301867
|
| 361 |
+
2032Q4,TransnetBW,924984.9939244165,15373489.605535902,0.06016753630166927,0.00202296444633885
|
| 362 |
+
2033Q1,TransnetBW,1107210.0339283668,15827433.247136606,0.06995512264306507,0.0016820905300179607
|
| 363 |
+
2033Q2,TransnetBW,594342.5971757444,13891501.634169815,0.04278461845433627,0.002628362250968557
|
| 364 |
+
2033Q3,TransnetBW,449672.1587744006,14011584.991966886,0.03209288307013135,0.003000725118130841
|
| 365 |
+
2033Q4,TransnetBW,934234.8438636607,15450357.05356358,0.060466877278294494,0.0020125392477803455
|
| 366 |
+
2034Q1,TransnetBW,1118282.1342676503,15906570.413372288,0.07030315807910022,0.0016699694413285088
|
| 367 |
+
2034Q2,TransnetBW,600286.0231475019,13960959.142340662,0.042997477252616566,0.002620948981786317
|
| 368 |
+
2034Q3,TransnetBW,454168.8803621446,14081642.91692672,0.03225254915505738,0.0029951644005265267
|
| 369 |
+
2034Q4,TransnetBW,943577.1923022972,15527608.838831395,0.0607677075135099,0.002002062182562346
|
| 370 |
+
2035Q1,TransnetBW,1129464.9556103267,15986103.265439145,0.07065292503471764,0.0016577880487152231
|
| 371 |
+
2035Q2,TransnetBW,606288.8833789768,14030763.938052364,0.04321139504989326,0.0026134988306678528
|
| 372 |
+
2035Q3,TransnetBW,458710.56916576606,14152051.131511353,0.03241300959861488,0.002989576017660499
|
| 373 |
+
2035Q4,TransnetBW,953012.9642253201,15605246.883025551,0.06107003441656218,0.001991532992641768
|
| 374 |
+
2036Q1,TransnetBW,1140759.6051664301,16066033.78176634,0.07100443212444262,0.0016455460521585946
|
| 375 |
+
2036Q2,TransnetBW,612351.7722127666,14100917.757742623,0.043426377114818115,0.002606011614120933
|
| 376 |
+
2036Q3,TransnetBW,463297.67485742376,14222811.387168907,0.03257426835283685,0.002983959831894638
|
| 377 |
+
2036Q4,TransnetBW,962543.0938675734,15683273.117440678,0.061373865433560014,0.001980951418691739
|
| 378 |
+
2037Q1,TransnetBW,1152167.2012180944,16146363.950675167,0.07135768800565877,0.0016332431501464538
|
| 379 |
+
2037Q2,TransnetBW,618475.2899348943,14171422.346531335,0.043642428742255025,0.0025984871477404484
|
| 380 |
+
2037Q3,TransnetBW,467930.651605998,14293925.444104752,0.03273632938941813,0.002978315704906063
|
| 381 |
+
2037Q4,TransnetBW,972168.5248062492,15761689.48302788,0.061679208047657336,0.001970317200095186
|
| 382 |
+
2038Q1,TransnetBW,1163688.8732302755,16227095.770428544,0.07171270137882124,0.001620879039666595
|
| 383 |
+
2038Q2,TransnetBW,624660.0428342433,14242279.458263991,0.04385955525341052,0.002590925246203843
|
| 384 |
+
2038Q3,TransnetBW,472609.95812205796,14365395.071325272,0.032899196699813255,0.002972643497683714
|
| 385 |
+
2038Q4,TransnetBW,981890.2100543117,15840497.930443017,0.06198606977923773,0.001959630074938455
|
| 386 |
+
2039Q1,TransnetBW,1175325.7619625782,16308231.249280684,0.07206948098767112,0.0016084534161992722
|
| 387 |
+
2039Q2,TransnetBW,630906.6432625856,14313490.855555309,0.04407776199596481,0.002583325723266555
|
| 388 |
+
2039Q3,TransnetBW,477336.05770327855,14437222.0466819,0.03306287429533471,0.0029669430705249362
|
| 389 |
+
2039Q4,TransnetBW,991709.1121548549,15919700.42009523,0.062294458186099626,0.0019488897800048234
|
| 390 |
+
2040Q1,TransnetBW,1187079.019582204,16389772.405527085,0.07242803561945059,0.0015959659737097218
|
| 391 |
+
2040Q2,TransnetBW,637215.7096952115,14385058.309833085,0.044297054344203446,0.002575688391757442
|
| 392 |
+
2040Q3,TransnetBW,482109.41828031134,14509408.156915307,0.0332273662072518,0.002961214283032032
|
| 393 |
+
2040Q4,TransnetBW,1001626.2032764034,15999298.922195705,0.06260438086364241,0.0019380960507680428
|
| 394 |
+
2041Q1,TransnetBW,1198949.809778026,16471721.26755472,0.0727883741051195,0.0015834164046406272
|
| 395 |
+
2041Q2,TransnetBW,643587.8667921636,14456983.60138225,0.04451743769914973,0.002568013063574154
|
| 396 |
+
2041Q3,TransnetBW,486930.51246311446,14581955.197699882,0.03339267648688988,0.0029554569941088182
|
| 397 |
+
2041Q4,TransnetBW,1011642.4653091675,16079295.416806683,0.06291584544505358,0.0019272486213858
|
| 398 |
+
2042Q1,TransnetBW,1210939.3078758062,16554079.873892492,0.07315050531957283,0.0015708043999045178
|
| 399 |
+
2042Q2,TransnetBW,650023.7454600853,14529268.519389158,0.04473891748869775,0.002560299549678513
|
| 400 |
+
2042Q3,TransnetBW,491799.81758774567,14654864.973688379,0.033558809205730136,0.0029496710619571244
|
| 401 |
+
2042Q4,TransnetBW,1021758.8899622591,16159691.893890712,0.06322885960149663,0.0019163472246932003
|
| 402 |
+
2043Q1,TransnetBW,1223048.7009545644,16636850.273261953,0.07351443818185927,0.0015581296488761942
|
| 403 |
+
2043Q2,TransnetBW,656523.9829146862,14601914.861986103,0.04496149916774601,0.002552547660091848
|
| 404 |
+
2043Q3,TransnetBW,496717.81576362305,14728139.298556818,0.03372576845550989,0.002943856344073341
|
| 405 |
+
2043Q4,TransnetBW,1031976.4788618817,16240490.353360163,0.0635434310423001,0.0019053915921961595
|
| 406 |
+
2044Q1,TransnetBW,1235279.18796411,16720034.52462826,0.07388018165540088,0.0015453918393850373
|
| 407 |
+
2044Q2,TransnetBW,663089.222743833,14674924.43629603,0.045185188218331805,0.002544757203890323
|
| 408 |
+
2044Q3,TransnetBW,501684.9939212593,14801779.995049601,0.033893558348323374,0.0029380126972448593
|
| 409 |
+
2044Q4,TransnetBW,1042296.2436505004,16321692.805126963,0.06385956751514738,0.0018943814540648071
|
| 410 |
+
2045Q1,TransnetBW,1247631.9798437513,16803634.697251398,0.07424774474821384,0.0015325906577073577
|
| 411 |
+
2045Q2,TransnetBW,669720.1149712714,14748299.058477508,0.04540999014976631,0.0025369279892002335
|
| 412 |
+
2045Q3,TransnetBW,506701.8438604719,14875788.89502485,0.034062183016722994,0.002932139977546582
|
| 413 |
+
2045Q4,TransnetBW,1052719.2060870056,16403301.269152595,0.06417727680626753,0.0018833165391268294
|
| 414 |
+
2046Q1,TransnetBW,1260108.2996421887,16887652.870737657,0.0746171365131303,0.001519725788558645
|
| 415 |
+
2046Q2,TransnetBW,676417.316120984,14822040.553769896,0.04563591049877012,0.0025290598231932776
|
| 416 |
+
2046Q3,TransnetBW,511768.86229907663,14950167.83949997,0.03423164661382112,0.00292623804033737
|
| 417 |
+
2046Q4,TransnetBW,1063246.3981478757,16485317.775498357,0.06449656674062708,0.0018721965748607974
|
model/revenue/curltailment_rate_per_tso/merge.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import glob
|
| 3 |
+
import re
|
| 4 |
+
import pandas as pd
|
| 5 |
+
|
| 6 |
+
# -------------------------------------------------
|
| 7 |
+
# CONFIG
|
| 8 |
+
# -------------------------------------------------
|
| 9 |
+
# Put the script in the same folder as your CSVs (recommended).
|
| 10 |
+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
| 11 |
+
|
| 12 |
+
# Which column to extract from each file:
|
| 13 |
+
VALUE_COL = "Wind onshore [MWh] Calculated resolutions"
|
| 14 |
+
|
| 15 |
+
# Output file
|
| 16 |
+
OUT_FILE = os.path.join(BASE_DIR, "wind_onshore_daily_by_tso.csv")
|
| 17 |
+
|
| 18 |
+
# Expected TSOs and filename patterns.
|
| 19 |
+
# Adjust these if your filenames differ.
|
| 20 |
+
TSO_PATTERNS = {
|
| 21 |
+
"TenneT": "Tennet*.csv", # note: your file uses 'Tennet' not 'TenneT'
|
| 22 |
+
"50Hertz": "50Hertz*.csv",
|
| 23 |
+
"Amprion": "Amprion*.csv",
|
| 24 |
+
"TransnetBW": "TransnetBW*.csv",
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
# If your filenames are slightly different, add more patterns or rename keys.
|
| 28 |
+
|
| 29 |
+
# -------------------------------------------------
|
| 30 |
+
def parse_numeric_series(s: pd.Series) -> pd.Series:
|
| 31 |
+
"""
|
| 32 |
+
Convert strings like '29,339.75' (US format with thousands comma)
|
| 33 |
+
or '29339.75' into float.
|
| 34 |
+
"""
|
| 35 |
+
s = s.astype(str).str.strip()
|
| 36 |
+
# remove thousands separators (commas) but keep decimal dot
|
| 37 |
+
s = s.str.replace(",", "", regex=False)
|
| 38 |
+
return pd.to_numeric(s, errors="coerce")
|
| 39 |
+
|
| 40 |
+
def read_one_tso(files, tso_name: str) -> pd.DataFrame:
|
| 41 |
+
"""
|
| 42 |
+
Read all files for one TSO, extract Start date + VALUE_COL,
|
| 43 |
+
return a daily series with columns: date, <tso_name>.
|
| 44 |
+
"""
|
| 45 |
+
parts = []
|
| 46 |
+
for f in sorted(files):
|
| 47 |
+
df = pd.read_csv(f, sep=";", dtype=str, encoding="utf-8", engine="python")
|
| 48 |
+
|
| 49 |
+
# Basic column checks
|
| 50 |
+
if "Start date" not in df.columns:
|
| 51 |
+
raise ValueError(f"'Start date' column not found in {f}")
|
| 52 |
+
if VALUE_COL not in df.columns:
|
| 53 |
+
raise ValueError(f"'{VALUE_COL}' not found in {f}. Available columns: {list(df.columns)}")
|
| 54 |
+
|
| 55 |
+
tmp = df[["Start date", VALUE_COL]].copy()
|
| 56 |
+
tmp = tmp.rename(columns={"Start date": "date", VALUE_COL: tso_name})
|
| 57 |
+
|
| 58 |
+
# Parse date (examples: 'Jan 1, 2015')
|
| 59 |
+
tmp["date"] = pd.to_datetime(tmp["date"], errors="coerce")
|
| 60 |
+
|
| 61 |
+
# Parse numeric
|
| 62 |
+
tmp[tso_name] = parse_numeric_series(tmp[tso_name])
|
| 63 |
+
|
| 64 |
+
parts.append(tmp)
|
| 65 |
+
|
| 66 |
+
out = pd.concat(parts, ignore_index=True)
|
| 67 |
+
|
| 68 |
+
# Drop bad dates, sort, dedupe (keep last in case of overlaps)
|
| 69 |
+
out = out.dropna(subset=["date"]).sort_values("date")
|
| 70 |
+
out = out.drop_duplicates(subset=["date"], keep="last").reset_index(drop=True)
|
| 71 |
+
|
| 72 |
+
# Keep only date part (daily frequency)
|
| 73 |
+
out["date"] = out["date"].dt.normalize()
|
| 74 |
+
|
| 75 |
+
return out
|
| 76 |
+
|
| 77 |
+
def main():
|
| 78 |
+
series_list = []
|
| 79 |
+
|
| 80 |
+
# Find and read each TSO
|
| 81 |
+
for tso, pattern in TSO_PATTERNS.items():
|
| 82 |
+
paths = glob.glob(os.path.join(BASE_DIR, pattern))
|
| 83 |
+
if not paths:
|
| 84 |
+
raise FileNotFoundError(f"No files found for {tso} using pattern: {pattern}")
|
| 85 |
+
|
| 86 |
+
df_tso = read_one_tso(paths, tso)
|
| 87 |
+
series_list.append(df_tso)
|
| 88 |
+
|
| 89 |
+
# Merge all TSOs on date (outer join to keep full coverage)
|
| 90 |
+
merged = series_list[0]
|
| 91 |
+
for df in series_list[1:]:
|
| 92 |
+
merged = merged.merge(df, on="date", how="outer")
|
| 93 |
+
|
| 94 |
+
merged = merged.sort_values("date").reset_index(drop=True)
|
| 95 |
+
|
| 96 |
+
# Optional: check missingness
|
| 97 |
+
print("Rows:", len(merged))
|
| 98 |
+
print("Date range:", merged["date"].min().date(), "→", merged["date"].max().date())
|
| 99 |
+
print("\nMissing values per column:")
|
| 100 |
+
print(merged.isna().sum())
|
| 101 |
+
|
| 102 |
+
merged.to_csv(OUT_FILE, index=False)
|
| 103 |
+
print(f"\nSaved: {OUT_FILE}")
|
| 104 |
+
|
| 105 |
+
if __name__ == "__main__":
|
| 106 |
+
main()
|
model/revenue/curltailment_rate_per_tso/pred_cr.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import statsmodels.formula.api as smf
|
| 4 |
+
|
| 5 |
+
# =============================
|
| 6 |
+
# CONFIG
|
| 7 |
+
# =============================
|
| 8 |
+
WIND_DAILY_FILE = "wind_onshore_daily_by_tso.csv"
|
| 9 |
+
LOAD_MONTHLY_FILE = "../monthly_gridload_per_tso/tso_grid_load_monthly_wide.csv"
|
| 10 |
+
CURTAIL_FILE = "curltailment_rate_quarterly_by_tso.csv"
|
| 11 |
+
|
| 12 |
+
FUTURE_START = "2021Q1"
|
| 13 |
+
FUTURE_END = "2046Q4"
|
| 14 |
+
|
| 15 |
+
CR_FLOOR = 0.0
|
| 16 |
+
CR_CAP = 0.30
|
| 17 |
+
|
| 18 |
+
TSOS = ["TenneT", "50Hertz", "Amprion", "TransnetBW"]
|
| 19 |
+
LOAD_COL_MAP = {
|
| 20 |
+
"TenneT": "load_mwh_tennet",
|
| 21 |
+
"50Hertz": "load_mwh_50hertz",
|
| 22 |
+
"Amprion": "load_mwh_amprion",
|
| 23 |
+
"TransnetBW": "load_mwh_transnetbw",
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
# Option B growth assumptions (scenario knobs)
|
| 27 |
+
G_WIND = {tso: 0.01 for tso in TSOS} # +1%/yr wind proxy
|
| 28 |
+
G_LOAD = {tso: 0.005 for tso in TSOS} # +0.5%/yr load proxy
|
| 29 |
+
|
| 30 |
+
LEVEL_QTRS = 8 # last 8 quarters average = baseline level
|
| 31 |
+
|
| 32 |
+
OUTPUT_FILE = "curtailment_forecast_quarterly_by_tso_2021_2046.csv"
|
| 33 |
+
|
| 34 |
+
# =============================
|
| 35 |
+
# HELPERS
|
| 36 |
+
# =============================
|
| 37 |
+
def to_quarter_period_from_dates(s):
|
| 38 |
+
return pd.to_datetime(s).dt.to_period("Q")
|
| 39 |
+
|
| 40 |
+
def wide_to_quarter_long(df, date_col, value_cols, value_name):
|
| 41 |
+
df = df.copy()
|
| 42 |
+
df[date_col] = pd.to_datetime(df[date_col])
|
| 43 |
+
df["quarter"] = to_quarter_period_from_dates(df[date_col])
|
| 44 |
+
long = df.melt(id_vars="quarter", value_vars=value_cols,
|
| 45 |
+
var_name="TSO", value_name=value_name)
|
| 46 |
+
return long.groupby(["quarter", "TSO"], as_index=False)[value_name].sum()
|
| 47 |
+
|
| 48 |
+
def make_season_factors(df_q, value_col):
|
| 49 |
+
"""
|
| 50 |
+
Returns season_factor per (TSO, q_num) normalized to mean=1 within each TSO.
|
| 51 |
+
"""
|
| 52 |
+
tmp = df_q.copy()
|
| 53 |
+
tmp["q_num"] = tmp["quarter"].dt.quarter.astype(int)
|
| 54 |
+
seas = tmp.groupby(["TSO", "q_num"])[value_col].mean().reset_index()
|
| 55 |
+
seas["mean_tso"] = seas.groupby("TSO")[value_col].transform("mean")
|
| 56 |
+
seas["season_factor"] = seas[value_col] / seas["mean_tso"]
|
| 57 |
+
return seas[["TSO", "q_num", "season_factor"]]
|
| 58 |
+
|
| 59 |
+
def make_future_series(df_q, value_col, g_map, future_q, last_q):
|
| 60 |
+
"""
|
| 61 |
+
level = mean of last LEVEL_QTRS for each TSO
|
| 62 |
+
season = avg by q_num per TSO (normalized)
|
| 63 |
+
growth = (1+g)^(years_ahead) where years_ahead = quarters_ahead/4
|
| 64 |
+
"""
|
| 65 |
+
df_q = df_q.copy().sort_values(["TSO", "quarter"])
|
| 66 |
+
|
| 67 |
+
# level per TSO (last LEVEL_QTRS) — warning-free
|
| 68 |
+
levels = (
|
| 69 |
+
df_q.groupby("TSO", as_index=True)[value_col]
|
| 70 |
+
.apply(lambda s: float(s.tail(LEVEL_QTRS).mean()))
|
| 71 |
+
.to_dict()
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
seas = make_season_factors(df_q, value_col)
|
| 75 |
+
|
| 76 |
+
future = pd.MultiIndex.from_product([future_q, TSOS], names=["quarter", "TSO"]).to_frame(index=False)
|
| 77 |
+
future["q_num"] = future["quarter"].dt.quarter.astype(int)
|
| 78 |
+
|
| 79 |
+
# FIX: last_q is a scalar Period
|
| 80 |
+
quarters_ahead = future["quarter"].apply(lambda p: p.ordinal) - last_q.ordinal
|
| 81 |
+
years_ahead = quarters_ahead / 4.0
|
| 82 |
+
|
| 83 |
+
future = future.merge(seas, on=["TSO", "q_num"], how="left")
|
| 84 |
+
future["season_factor"] = future["season_factor"].fillna(1.0)
|
| 85 |
+
|
| 86 |
+
out = []
|
| 87 |
+
for tso in TSOS:
|
| 88 |
+
g = float(g_map[tso])
|
| 89 |
+
lvl = float(levels[tso])
|
| 90 |
+
|
| 91 |
+
idx = future["TSO"] == tso
|
| 92 |
+
growth = (1.0 + g) ** years_ahead[idx].values
|
| 93 |
+
vals = lvl * future.loc[idx, "season_factor"].values * growth
|
| 94 |
+
|
| 95 |
+
out.append(pd.DataFrame({
|
| 96 |
+
"quarter": future.loc[idx, "quarter"].values,
|
| 97 |
+
"TSO": tso,
|
| 98 |
+
value_col: vals
|
| 99 |
+
}))
|
| 100 |
+
|
| 101 |
+
out = pd.concat(out, ignore_index=True).sort_values(["quarter", "TSO"]).reset_index(drop=True)
|
| 102 |
+
return out
|
| 103 |
+
|
| 104 |
+
# =============================
|
| 105 |
+
# LOAD & PREPROCESS
|
| 106 |
+
# =============================
|
| 107 |
+
# Wind (daily -> quarterly)
|
| 108 |
+
wind = pd.read_csv(WIND_DAILY_FILE)
|
| 109 |
+
wind_q = wide_to_quarter_long(wind, "date", TSOS, "wind_mwh")
|
| 110 |
+
|
| 111 |
+
# Load (monthly -> quarterly)
|
| 112 |
+
load = pd.read_csv(LOAD_MONTHLY_FILE)
|
| 113 |
+
load = load.rename(columns={v: k for k, v in LOAD_COL_MAP.items()})
|
| 114 |
+
load_q = wide_to_quarter_long(load, "date", TSOS, "load_mwh")
|
| 115 |
+
|
| 116 |
+
# Curtailment (quarterly by TSO in wide columns)
|
| 117 |
+
curt = pd.read_csv(CURTAIL_FILE)
|
| 118 |
+
|
| 119 |
+
# Parse quarter like "2015Q1" safely
|
| 120 |
+
curt["quarter"] = pd.PeriodIndex(curt["quarter"].astype(str), freq="Q")
|
| 121 |
+
|
| 122 |
+
records = []
|
| 123 |
+
for tso in TSOS:
|
| 124 |
+
records.append(pd.DataFrame({
|
| 125 |
+
"quarter": curt["quarter"],
|
| 126 |
+
"TSO": tso,
|
| 127 |
+
"cr": pd.to_numeric(curt[f"{tso}_curtailment_rate"], errors="coerce"),
|
| 128 |
+
"prod_mwh": pd.to_numeric(curt[f"{tso}_production_mwh"], errors="coerce"),
|
| 129 |
+
"curt_mwh": pd.to_numeric(curt[f"{tso}_curtailed_mwh"], errors="coerce"),
|
| 130 |
+
}))
|
| 131 |
+
curt_q = pd.concat(records, ignore_index=True).dropna(subset=["quarter", "TSO", "cr"])
|
| 132 |
+
|
| 133 |
+
# Merge historical modeling frame
|
| 134 |
+
df = curt_q.merge(wind_q, on=["quarter", "TSO"], how="inner").merge(load_q, on=["quarter", "TSO"], how="inner")
|
| 135 |
+
df["S"] = df["wind_mwh"] / df["load_mwh"]
|
| 136 |
+
|
| 137 |
+
# =============================
|
| 138 |
+
# FIT MODEL 0 ON ALL HISTORY
|
| 139 |
+
# =============================
|
| 140 |
+
model0 = smf.ols("cr ~ S * C(TSO)", data=df).fit()
|
| 141 |
+
print(model0.summary())
|
| 142 |
+
|
| 143 |
+
# =============================
|
| 144 |
+
# FUTURE QUARTERS 2021Q1–2046Q4
|
| 145 |
+
# =============================
|
| 146 |
+
future_q = pd.period_range(pd.Period(FUTURE_START, freq="Q"),
|
| 147 |
+
pd.Period(FUTURE_END, freq="Q"),
|
| 148 |
+
freq="Q")
|
| 149 |
+
|
| 150 |
+
# last observed quarter for growth baseline
|
| 151 |
+
last_q_wind = wind_q["quarter"].max()
|
| 152 |
+
last_q_load = load_q["quarter"].max()
|
| 153 |
+
last_q = max(last_q_wind, last_q_load)
|
| 154 |
+
|
| 155 |
+
# =============================
|
| 156 |
+
# OPTION B: forecast wind & load -> future S
|
| 157 |
+
# =============================
|
| 158 |
+
wind_f = make_future_series(wind_q, "wind_mwh", G_WIND, future_q=future_q, last_q=last_q)
|
| 159 |
+
load_f = make_future_series(load_q, "load_mwh", G_LOAD, future_q=future_q, last_q=last_q)
|
| 160 |
+
|
| 161 |
+
future = wind_f.merge(load_f, on=["quarter", "TSO"], how="inner")
|
| 162 |
+
future["S"] = future["wind_mwh"] / future["load_mwh"]
|
| 163 |
+
|
| 164 |
+
# =============================
|
| 165 |
+
# PREDICT CURTAILMENT
|
| 166 |
+
# =============================
|
| 167 |
+
future["cr_hat"] = model0.predict(future).clip(CR_FLOOR, CR_CAP)
|
| 168 |
+
|
| 169 |
+
out = future[["quarter", "TSO", "wind_mwh", "load_mwh", "S", "cr_hat"]].copy()
|
| 170 |
+
out = out.sort_values(["TSO", "quarter"]).reset_index(drop=True)
|
| 171 |
+
|
| 172 |
+
out.to_csv(OUTPUT_FILE, index=False)
|
| 173 |
+
print(f"\nSaved: {OUTPUT_FILE}")
|
| 174 |
+
print(f"Quarter parsing OK (example): {curt['quarter'].iloc[0]}")
|
| 175 |
+
print(f"Baseline last_q used for growth: {last_q}")
|
model/revenue/curltailment_rate_per_tso/wind_onshore_daily_by_tso.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/day_ahead_market_prices/eh1516.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/day_ahead_market_prices/eh1718.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/day_ahead_market_prices/eh1920.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/day_ahead_market_prices/eh2122.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/day_ahead_market_prices/eh2324.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/day_ahead_market_prices/eh25.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model/revenue/day_ahead_market_prices/market_price_forecast_20y_monthly.csv
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
date,price_eur_mwh_forecast,log_price_shifted_forecast,mu_log_shifted
|
| 2 |
+
2026-01-01,44.594443155319794,5.499601504905559,10.090382171916277
|
| 3 |
+
2026-02-01,39.8876563183496,5.480170715076063,10.091211366154042
|
| 4 |
+
2026-03-01,40.31309723395208,5.481942644935687,10.092040560391805
|
| 5 |
+
2026-04-01,33.71001488980778,5.4540810942415465,10.092869754629568
|
| 6 |
+
2026-05-01,32.24481358096807,5.447792046253938,10.093698948867333
|
| 7 |
+
2026-06-01,39.17433840003221,5.477192735385145,10.094528143105096
|
| 8 |
+
2026-07-01,46.79436025343941,5.50855544028488,10.095357337342861
|
| 9 |
+
2026-08-01,54.5263014655435,5.539404176291427,10.096186531580624
|
| 10 |
+
2026-09-01,55.389489699997256,5.542789790441547,10.09701572581839
|
| 11 |
+
2026-10-01,45.62275007189419,5.503796822568928,10.097844920056152
|
| 12 |
+
2026-11-01,54.667081420068826,5.53995712910992,10.098674114293917
|
| 13 |
+
2026-12-01,55.9591260499198,5.5450177678644295,10.09950330853168
|
| 14 |
+
2027-01-01,47.77805957013297,5.512533424395862,10.100332502769445
|
| 15 |
+
2027-02-01,42.94185981096632,5.492822154676124,10.101161697007209
|
| 16 |
+
2027-03-01,43.3108854302921,5.4943399895625475,10.101990891244974
|
| 17 |
+
2027-04-01,36.57096983074101,5.466248246766748,10.102820085482737
|
| 18 |
+
2027-05-01,35.03881271384006,5.4597506609910935,10.103649279720502
|
| 19 |
+
2027-06-01,42.00597831031092,5.488962429613169,10.104478473958265
|
| 20 |
+
2027-07-01,49.673480418633176,5.520153985873101,10.105307668196028
|
| 21 |
+
2027-08-01,57.455701758413284,5.550847673298426,10.106136862433793
|
| 22 |
+
2027-09-01,58.29254150962663,5.554092824383411,10.106966056671556
|
| 23 |
+
2027-10-01,48.383173167497375,5.5149726068932186,10.107795250909321
|
| 24 |
+
2027-11-01,57.499462897584124,5.551017634266991,10.108624445147084
|
| 25 |
+
2027-12-01,58.77885059214668,5.555973838236961,10.10945363938485
|
| 26 |
+
2028-01-01,50.483959421399845,5.523394884228731,10.110282833622612
|
| 27 |
+
2028-02-01,45.57389601527561,5.503597904041414,10.111112027860377
|
| 28 |
+
2028-03-01,45.92782321017441,5.50503809129704,10.11194122209814
|
| 29 |
+
2028-04-01,39.0985966704842,5.47687600523118,10.112770416335906
|
| 30 |
+
2028-05-01,37.53493168075448,5.470314693420453,10.113599610573669
|
| 31 |
+
2028-06-01,44.5619694917919,5.4994687307550585,10.114428804811434
|
| 32 |
+
2028-07-01,52.29725774059088,5.530607986545498,10.115257999049197
|
| 33 |
+
2028-08-01,60.14893487070765,5.561254293438896,10.116087193286962
|
| 34 |
+
2028-09-01,60.983326230568366,5.564456521107945,10.116916387524725
|
| 35 |
+
2028-10-01,50.960967239780445,5.525297418034146,10.11774558176249
|
| 36 |
+
2028-11-01,60.16270345518876,5.561307217815251,10.118574776000253
|
| 37 |
+
2028-12-01,61.44697960060353,5.56623150807402,10.119403970238016
|
| 38 |
+
2029-01-01,53.0592478400047,5.533623642497176,10.120233164475781
|
| 39 |
+
2029-02-01,48.09220476406074,5.513800470470412,10.121062358713544
|
| 40 |
+
2029-03-01,48.44386627275534,5.5152169297691565,10.12189155295131
|
| 41 |
+
2029-04-01,41.539578996819955,5.487033347850016,10.122720747189073
|
| 42 |
+
2029-05-01,39.955277520734455,5.480452562314247,10.123549941426838
|
| 43 |
+
2029-06-01,47.049558407765915,5.509588957829186,10.1243791356646
|
| 44 |
+
2029-07-01,54.85945373180962,5.540712231376867,10.125208329902366
|
| 45 |
+
2029-08-01,62.7870634303689,5.571344059486982,10.126037524140129
|
| 46 |
+
2029-09-01,63.62645827259104,5.574533170400865,10.126866718377894
|
| 47 |
+
2029-10-01,53.499584625872416,5.535362184473179,10.127695912615657
|
| 48 |
+
2029-11-01,62.79157282696548,5.57136121922783,10.128525106853422
|
| 49 |
+
2029-12-01,64.08625073875174,5.57627575713285,10.129354301091185
|
| 50 |
+
2030-01-01,55.611587660874505,5.543659056612215,10.13018349532895
|
| 51 |
+
2030-02-01,50.59244158904281,5.523827880750296,10.131012689566713
|
| 52 |
+
2030-03-01,50.94582749874303,5.525237089139615,10.131841883804476
|
| 53 |
+
2030-04-01,43.970407794765265,5.4970469384085945,10.132671078042241
|
| 54 |
+
2030-05-01,42.36871976466685,5.490460201993145,10.133500272280004
|
| 55 |
+
2030-06-01,49.5330088476656,5.519591206431345,10.13432946651777
|
| 56 |
+
2030-07-01,57.42015543615912,5.550709596044214,10.135158660755533
|
| 57 |
+
2030-08-01,65.42624345391704,5.581336999654292,10.135987854993298
|
| 58 |
+
2030-09-01,66.27300106892642,5.584522102283594,10.13681704923106
|
| 59 |
+
2030-10-01,56.043534108496544,5.545347485133146,10.137646243468826
|
| 60 |
+
2030-11-01,65.4278972243822,5.5813432302564046,10.138475437706589
|
| 61 |
+
2030-12-01,66.73476842458899,5.5862547879876985,10.139304631944354
|
| 62 |
+
2031-01-01,58.174416030150326,5.553635387640124,10.140133826182117
|
| 63 |
+
2031-02-01,53.104327635604335,5.53380176592566,10.140963020419882
|
| 64 |
+
2031-03-01,53.46069420035994,5.5352087585452985,10.141792214657645
|
| 65 |
+
2031-04-01,46.41487532724648,5.507016600483423,10.14262140889541
|
| 66 |
+
2031-05-01,44.79669398114041,5.500428045567976,10.143450603133173
|
| 67 |
+
2031-06-01,52.03233747031638,5.5295574025736,10.144279797370938
|
| 68 |
+
2031-07-01,59.99809387246307,5.5606742997288965,10.145108991608701
|
| 69 |
+
2031-08-01,68.08399652588372,5.591300351277809,10.145938185846465
|
| 70 |
+
2031-09-01,68.93890343689054,5.594484229035179,10.14676738008423
|
| 71 |
+
2031-10-01,58.60673297125959,5.555308502237256,10.147596574321993
|
| 72 |
+
2031-11-01,68.08477150970634,5.59130324209827,10.148425768559758
|
| 73 |
+
2031-12-01,69.40447885444422,5.596213889132958,10.14925496279752
|
| 74 |
+
2032-01-01,60.75823197554888,5.563593663758574,10.150084157035286
|
| 75 |
+
2032-02-01,55.63721094344635,5.5437592946280825,10.150913351273049
|
| 76 |
+
2032-03-01,55.99697042740411,5.545165610141584,10.151742545510814
|
| 77 |
+
2032-04-01,48.88049429607648,5.516972838669362,10.152571739748577
|
| 78 |
+
2032-05-01,47.24598408552714,5.510383728047464,10.153400933986342
|
| 79 |
+
2032-06-01,54.553894969079835,5.539512581622283,10.154230128224105
|
| 80 |
+
2032-07-01,62.599228176701786,5.570629022704825,10.15505932246187
|
| 81 |
+
2032-08-01,70.76591385385802,5.6012546610840275,10.155888516699633
|
| 82 |
+
2032-09-01,71.62927159807685,5.604438164538819,10.156717710937398
|
| 83 |
+
2032-10-01,61.193653242804544,5.565262098649194,10.157546905175161
|
| 84 |
+
2032-11-01,70.76642024969038,5.60125653131707,10.158376099412925
|
| 85 |
+
2032-12-01,72.09925288715021,5.606166900056472,10.15920529365069
|
| 86 |
+
2033-01-01,63.36645373628602,5.57354642256621,10.160034487888453
|
| 87 |
+
2033-02-01,58.19415096456606,5.553711825036538,10.160863682126218
|
| 88 |
+
2033-03-01,58.55745534354651,5.555117933636508,10.16169287636398
|
| 89 |
+
2033-04-01,51.369753009473925,5.526924974715243,10.162522070601746
|
| 90 |
+
2033-05-01,49.71885231054458,5.520335694277747,10.163351264839509
|
| 91 |
+
2033-06-01,57.09981482116547,5.549464394011629,10.164180459077274
|
| 92 |
+
2033-07-01,65.22557643528586,5.580580695725143,10.165009653315037
|
| 93 |
+
2033-08-01,73.4739055114834,5.611206207845852,10.165838847552802
|
| 94 |
+
2033-09-01,74.34586651337332,5.614389596919362,10.166668041790565
|
| 95 |
+
2033-10-01,63.8058530285486,5.575213427408377,10.16749723602833
|
| 96 |
+
2033-11-01,73.47433168172603,5.611207766202616,10.168326430266093
|
| 97 |
+
2033-12-01,74.82047049100709,5.616118049899132,10.169155624503858
|
| 98 |
+
2034-01-01,66.00031563161656,5.58349749536602,10.169984818741622
|
| 99 |
+
2034-02-01,60.776267755249705,5.5636628280409655,10.170814012979385
|
| 100 |
+
2034-03-01,61.143188912655944,5.565068873411253,10.17164320721715
|
| 101 |
+
2034-04-01,53.88359059186001,5.536875857208356,10.172472401454913
|
| 102 |
+
2034-05-01,52.216166877849616,5.5302865248777495,10.173301595692678
|
| 103 |
+
2034-06-01,59.67093053155702,5.559415177600135,10.174130789930441
|
| 104 |
+
2034-07-01,67.87794206874867,5.590531436724557,10.174959984168206
|
| 105 |
+
2034-08-01,76.20874719567752,5.621156910262554,10.175789178405969
|
| 106 |
+
2034-09-01,77.0894184496504,5.624340264382854,10.176618372643734
|
| 107 |
+
2034-10-01,66.4439928096333,5.585164063206726,10.177447566881497
|
| 108 |
+
2034-11-01,76.20915130374135,5.621158373314584,10.178276761119262
|
| 109 |
+
2034-12-01,77.56874466330521,5.626068631023262,10.179105955357025
|
| 110 |
+
2035-01-01,68.66037970070784,5.593448052947007,10.17993514959479
|
| 111 |
+
2035-02-01,63.38408453172809,5.573613364293528,10.180764343832553
|
| 112 |
+
2035-03-01,63.754669880547,5.575019390341767,10.181593538070318
|
| 113 |
+
2035-04-01,56.42246972366303,5.546826356634458,10.182422732308082
|
| 114 |
+
2035-05-01,54.73836744903937,5.540237008446092,10.183251926545847
|
| 115 |
+
2035-06-01,62.26767612138377,5.569365646802467,10.18408112078361
|
| 116 |
+
2035-07-01,70.55675539954859,5.6004818929122955,10.184910315021373
|
| 117 |
+
2035-08-01,78.97086634317583,5.631107354659992,10.185739509259138
|
| 118 |
+
2035-09-01,79.86034142144422,5.63429069809911,10.186568703496901
|
| 119 |
+
2035-10-01,69.10845781505611,5.5951144872465886,10.187397897734666
|
| 120 |
+
2035-11-01,78.97126636768934,5.631108788588316,10.18822709197243
|
| 121 |
+
2035-12-01,80.34445355042078,5.636019038355501,10.189056286210194
|
| 122 |
+
2036-01-01,71.34700229789246,5.603398453084811,10.189885480447957
|
| 123 |
+
2036-02-01,66.01794207418999,5.5835637579136845,10.190714674685722
|
| 124 |
+
2036-03-01,66.3922317270688,5.584969778057392,10.191543868923485
|
| 125 |
+
2036-04-01,58.98670776217796,5.556776739000998,10.19237306316125
|
| 126 |
+
2036-05-01,57.28576313040668,5.550187385966736,10.193202257399014
|
| 127 |
+
2036-06-01,64.8903640814836,5.579316019933074,10.194031451636778
|
| 128 |
+
2036-07-01,73.2623334195938,5.610432262065839,10.194860645874542
|
| 129 |
+
2036-08-01,81.76058478297745,5.641057720210597,10.195689840112307
|
| 130 |
+
2036-09-01,82.65895372059816,5.644241060385705,10.19651903435007
|
| 131 |
+
2036-10-01,71.79955013309637,5.605064846576219,10.197348228587833
|
| 132 |
+
2036-11-01,81.76098630014172,5.641059145239149,10.198177422825598
|
| 133 |
+
2036-12-01,83.14790470333486,5.645969392579529,10.199006617063361
|
| 134 |
+
2037-01-01,74.06047812337567,5.613348805110329,10.199835811301126
|
| 135 |
+
2037-02-01,68.67812664835361,5.593514107947505,10.20066500553889
|
| 136 |
+
2037-03-01,69.05615871954478,5.594920126286878,10.201494199776654
|
| 137 |
+
2037-04-01,61.576578957463994,5.566727085595883,10.202323394014417
|
| 138 |
+
2037-05-01,59.85862446752458,5.560137731080789,10.203152588252182
|
| 139 |
+
2037-06-01,67.5392711787328,5.589266363705596,10.203981782489945
|
| 140 |
+
2037-07-01,75.99495998404115,5.62038260462303,10.20481097672771
|
| 141 |
+
2037-08-01,84.57819364819437,5.651008061666781,10.205640170965474
|
| 142 |
+
2037-09-01,85.4855460000602,5.65419140084446,10.206469365203239
|
| 143 |
+
2037-10-01,74.51754802327457,5.615015186131371,10.207298559441002
|
| 144 |
+
2037-11-01,84.57859840658534,5.651009483975701,10.208127753678767
|
| 145 |
+
2037-12-01,85.97938579277292,5.655919730574487,10.20895694791653
|
| 146 |
+
2038-01-01,76.80108469550021,5.623299142433453,10.209786142154293
|
| 147 |
+
2038-02-01,71.36490950539496,5.603464444661998,10.210615336392058
|
| 148 |
+
2038-03-01,71.74672174970044,5.604870462449991,10.211444530629821
|
| 149 |
+
2038-04-01,64.1923460179193,5.576677421259488,10.212273724867586
|
| 150 |
+
2038-05-01,62.45721185596574,5.570088066291871,10.21310291910535
|
| 151 |
+
2038-06-01,70.214664957318,5.599216698506728,10.213932113343114
|
| 152 |
+
2038-07-01,78.75491058086925,5.6303329390527725,10.214761307580877
|
| 153 |
+
2038-08-01,87.42397651596599,5.660958395760074,10.215590501818642
|
| 154 |
+
2038-09-01,88.34040230643274,5.66414173463295,10.216419696056406
|
| 155 |
+
2038-10-01,77.26272424080327,5.624965519643736,10.21724889029417
|
| 156 |
+
2038-11-01,87.42438508306878,5.660959817237911,10.218078084531934
|
| 157 |
+
2038-12-01,88.83918028107018,5.665870063610079,10.218907278769699
|
| 158 |
+
2039-01-01,79.56909609519778,5.633249475263744,10.219736473007462
|
| 159 |
+
2039-02-01,74.07855909136009,5.613414777306299,10.220565667245227
|
| 160 |
+
2039-03-01,74.46418941255416,5.6148207949258,10.22139486148299
|
| 161 |
+
2039-04-01,66.83426987034437,5.586627753582654,10.222224055720755
|
| 162 |
+
2039-05-01,65.08178432753851,5.580038398476753,10.223053249958518
|
| 163 |
+
2039-06-01,72.91681193614801,5.609167030566333,10.223882444196281
|
| 164 |
+
2039-07-01,81.54245999438939,5.640283270998889,10.224711638434046
|
| 165 |
+
2039-08-01,90.29821656855955,5.670908727603376,10.22554083267181
|
| 166 |
+
2039-09-01,91.22380659072292,5.674092066383111,10.226370026909574
|
| 167 |
+
2039-10-01,80.03535171077118,5.634915851309515,10.227199221147337
|
| 168 |
+
2039-11-01,90.29862914760832,5.670910148827248,10.228028415385102
|
| 169 |
+
2039-12-01,91.72757227843869,5.675820395130163,10.228857609622866
|
| 170 |
+
2040-01-01,82.36478722674906,5.643199806721093,10.22968680386063
|
| 171 |
+
2040-02-01,76.81934483378916,5.623365108706811,10.230515998098394
|
| 172 |
+
2040-03-01,77.20883144413546,5.624771126274824,10.231345192336159
|
| 173 |
+
2040-04-01,69.50261269011042,5.59657808488503,10.232174386573922
|
| 174 |
+
2040-05-01,67.73260227976863,5.589988729736874,10.233003580811687
|
| 175 |
+
2040-06-01,75.64598015713221,5.619117361788172,10.23383277504945
|
| 176 |
+
2040-07-01,84.35788468930582,5.650233602186047,10.234661969287215
|
| 177 |
+
2040-08-01,93.20119882295933,5.680859058759115,10.235491163524978
|
| 178 |
+
2040-09-01,94.13604473725479,5.684042397510386,10.236320357762743
|
| 179 |
+
2040-10-01,82.83570529811294,5.644866182411004,10.237149552000506
|
| 180 |
+
2040-11-01,93.20161550504315,5.680860479905377,10.23797874623827
|
| 181 |
+
2040-12-01,94.64484806127126,5.68577072618713,10.238807940476034
|
| 182 |
+
2041-01-01,85.1884351516693,5.653150137758885,10.239637134713798
|
| 183 |
+
2041-02-01,79.58753832889005,5.6333154397272365,10.240466328951563
|
| 184 |
+
2041-03-01,79.98091980100014,5.634721457279515,10.241295523189326
|
| 185 |
+
2041-04-01,72.19763885437624,5.606528415875468,10.24212471742709
|
| 186 |
+
2041-05-01,70.40992833619299,5.599939060714397,10.242953911664854
|
| 187 |
+
2041-06-01,78.40243999006759,5.629067692753997,10.243783105902619
|
| 188 |
+
2041-07-01,87.20146356550998,5.660183933141273,10.244612300140382
|
| 189 |
+
2041-08-01,96.13321083856891,5.690809389704741,10.245441494378147
|
| 190 |
+
2041-09-01,97.0774052095104,5.693992728447314,10.24627068861591
|
| 191 |
+
2041-10-01,85.66406237277067,5.654816513340053,10.247099882853675
|
| 192 |
+
2041-11-01,96.13363168045043,5.690810810827287,10.247929077091438
|
| 193 |
+
2041-12-01,97.59129656041682,5.695721057102574,10.248758271329203
|
| 194 |
+
2042-01-01,88.0403195194366,5.663100468668471,10.249587465566966
|
| 195 |
+
2042-02-01,82.3834137266116,5.643265770631515,10.25041665980473
|
| 196 |
+
2042-03-01,82.78072901210379,5.644671788178986,10.251245854042494
|
| 197 |
+
2042-04-01,74.91961525445168,5.616478746770582,10.252075048280258
|
| 198 |
+
2042-05-01,73.1140276299339,5.609889391605567,10.252904242518023
|
| 199 |
+
2042-06-01,81.18646439964851,5.639018023641592,10.253733436755786
|
| 200 |
+
2042-07-01,90.0734782102125,5.670134264025631,10.25456263099355
|
| 201 |
+
2042-08-01,99.09454295540507,5.700759720586163,10.255391825231314
|
| 202 |
+
2042-09-01,100.0481792692861,5.70394305932608,10.256221019469079
|
| 203 |
+
2042-10-01,88.52070300318843,5.664766844216409,10.257050213706842
|
| 204 |
+
2042-11-01,99.09496800353827,5.700761141701463,10.257879407944607
|
| 205 |
+
2042-12-01,100.5672095317405,5.705671387974771,10.25870860218237
|
| 206 |
+
2043-01-01,90.9207227196465,5.6730507995388795,10.259537796420135
|
| 207 |
+
2043-02-01,85.20724786833222,5.653216101500301,10.260366990657898
|
| 208 |
+
2043-03-01,85.60853630626599,5.654622119046303,10.261196184895663
|
| 209 |
+
2043-04-01,77.66881141055563,5.626429077636569,10.262025379133426
|
| 210 |
+
2043-05-01,75.84516790943604,5.6198397224703465,10.26285457337119
|
| 211 |
+
2043-06-01,83.9983290466327,5.64896835450528,10.263683767608955
|
| 212 |
+
2043-07-01,92.97421299510637,5.680084594888328,10.264512961846718
|
| 213 |
+
2043-08-01,102.0854883875678,5.7107100514479665,10.265342156084483
|
| 214 |
+
2043-09-01,103.0486610643494,5.71389339018707,10.266171350322246
|
| 215 |
+
2043-10-01,91.4059100352859,5.674717175076665,10.26700054456001
|
| 216 |
+
2043-11-01,102.08591768551321,5.7107114725610515,10.267829738797774
|
| 217 |
+
2043-12-01,103.57288162882418,5.7156217188337575,10.268658933035539
|
| 218 |
+
2044-01-01,93.82992994839128,5.683001130397317,10.269488127273302
|
| 219 |
+
2044-02-01,88.05932034839117,5.663166432358245,10.270317321511067
|
| 220 |
+
2044-03-01,88.4646216705761,5.664572449903796,10.27114651574883
|
| 221 |
+
2044-04-01,80.44549952576034,5.6363794084936565,10.271975709986595
|
| 222 |
+
2044-05-01,78.6036195895199,5.629790053327066,10.272804904224358
|
| 223 |
+
2044-06-01,86.83831233802204,5.658918685361666,10.273634098462123
|
| 224 |
+
2044-07-01,95.90395512592022,5.690034925744412,10.274463292699886
|
| 225 |
+
2044-08-01,105.10634327224909,5.720660382303775,10.275292486937651
|
| 226 |
+
2044-09-01,106.07914767572493,5.72384372104263,10.276121681175415
|
| 227 |
+
2044-10-01,94.31996913627626,5.6846675059319995,10.276950875413178
|
| 228 |
+
2044-11-01,105.10677686296742,5.720661803416183,10.277780069650943
|
| 229 |
+
2044-12-01,106.60861044565729,5.725572049688703,10.278609263888706
|
| 230 |
+
2045-01-01,96.76822924835352,5.692951461252097,10.27943845812647
|
| 231 |
+
2045-02-01,90.93991355229906,5.67311676321287,10.280267652364234
|
| 232 |
+
2045-03-01,91.34926788766711,5.674522780758286,10.281096846601999
|
| 233 |
+
2045-04-01,83.24995452135676,5.646329739348021,10.281926040839762
|
| 234 |
+
2045-05-01,81.38965578572021,5.6397403841813185,10.282755235077527
|
| 235 |
+
2045-06-01,89.70669546168648,5.668869016215815,10.28358442931529
|
| 236 |
+
2045-07-01,98.86299467744556,5.69998525659847,10.284413623553055
|
| 237 |
+
2045-08-01,108.15740670521978,5.730610713157748,10.285242817790818
|
| 238 |
+
2045-09-01,109.13993915270811,5.7337940518965285,10.286072012028583
|
| 239 |
+
2045-10-01,97.26316882783567,5.694617836785829,10.286901206266347
|
| 240 |
+
2045-11-01,108.15784463178181,5.7306121342699505,10.287730400504111
|
| 241 |
+
2045-12-01,109.67469655028236,5.735522380542415,10.288559594741875
|
model/revenue/day_ahead_market_prices/market_price_monthly_history.csv
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
date,price_eur_mwh
|
| 2 |
+
2015-01-01,31.05307098765432
|
| 3 |
+
2015-02-01,36.71691964285714
|
| 4 |
+
2015-03-01,31.34314939434724
|
| 5 |
+
2015-04-01,29.724375
|
| 6 |
+
2015-05-01,25.357916666666668
|
| 7 |
+
2015-06-01,30.06438888888889
|
| 8 |
+
2015-07-01,34.99568548387097
|
| 9 |
+
2015-08-01,31.605094086021502
|
| 10 |
+
2015-09-01,31.881319444444443
|
| 11 |
+
2015-10-01,39.38145161290323
|
| 12 |
+
2015-11-01,32.389375
|
| 13 |
+
2015-12-01,27.780604838709678
|
| 14 |
+
2016-01-01,29.035524193548387
|
| 15 |
+
2016-02-01,21.989554597701147
|
| 16 |
+
2016-03-01,24.30504710632571
|
| 17 |
+
2016-04-01,24.21348611111111
|
| 18 |
+
2016-05-01,22.54236559139785
|
| 19 |
+
2016-06-01,27.69377777777778
|
| 20 |
+
2016-07-01,27.188306451612902
|
| 21 |
+
2016-08-01,27.182567204301076
|
| 22 |
+
2016-09-01,30.493861111111112
|
| 23 |
+
2016-10-01,37.135551075268815
|
| 24 |
+
2016-11-01,38.222541666666665
|
| 25 |
+
2016-12-01,37.477889784946235
|
| 26 |
+
2017-01-01,52.372956989247314
|
| 27 |
+
2017-02-01,39.70160714285714
|
| 28 |
+
2017-03-01,31.701386271870795
|
| 29 |
+
2017-04-01,28.86991666666667
|
| 30 |
+
2017-05-01,30.460510752688172
|
| 31 |
+
2017-06-01,30.00161111111111
|
| 32 |
+
2017-07-01,33.009112903225805
|
| 33 |
+
2017-08-01,30.848387096774193
|
| 34 |
+
2017-09-01,34.34861111111111
|
| 35 |
+
2017-10-01,28.401478494623657
|
| 36 |
+
2017-11-01,40.366625
|
| 37 |
+
2017-12-01,30.765725806451613
|
| 38 |
+
2018-01-01,29.46159946236559
|
| 39 |
+
2018-02-01,40.11510416666666
|
| 40 |
+
2018-03-01,37.36347240915209
|
| 41 |
+
2018-04-01,32.056263888888886
|
| 42 |
+
2018-05-01,33.54216397849462
|
| 43 |
+
2018-06-01,42.42323611111111
|
| 44 |
+
2018-07-01,49.54345430107527
|
| 45 |
+
2018-08-01,56.189408602150536
|
| 46 |
+
2018-09-01,54.832138888888885
|
| 47 |
+
2018-10-01,53.12668010752688
|
| 48 |
+
2018-11-01,56.676013888888896
|
| 49 |
+
2018-12-01,48.13212365591398
|
| 50 |
+
2019-01-01,49.393373655913976
|
| 51 |
+
2019-02-01,42.82078869047619
|
| 52 |
+
2019-03-01,30.626958277254378
|
| 53 |
+
2019-04-01,36.95590277777778
|
| 54 |
+
2019-05-01,37.84356182795699
|
| 55 |
+
2019-06-01,32.517583333333334
|
| 56 |
+
2019-07-01,39.68502688172043
|
| 57 |
+
2019-08-01,36.84849462365591
|
| 58 |
+
2019-09-01,35.75070833333333
|
| 59 |
+
2019-10-01,36.999556451612904
|
| 60 |
+
2019-11-01,41.00120833333333
|
| 61 |
+
2019-12-01,31.966142473118282
|
| 62 |
+
2020-01-01,35.0349059139785
|
| 63 |
+
2020-02-01,21.919008620689652
|
| 64 |
+
2020-03-01,22.485827725437417
|
| 65 |
+
2020-04-01,17.093125
|
| 66 |
+
2020-05-01,17.596505376344084
|
| 67 |
+
2020-06-01,26.18488888888889
|
| 68 |
+
2020-07-01,30.062862903225806
|
| 69 |
+
2020-08-01,34.86395161290322
|
| 70 |
+
2020-09-01,43.690194444444444
|
| 71 |
+
2020-10-01,34.01510752688172
|
| 72 |
+
2020-11-01,38.78570833333333
|
| 73 |
+
2020-12-01,43.51974462365591
|
| 74 |
+
2021-01-01,52.806223118279576
|
| 75 |
+
2021-02-01,48.70494047619048
|
| 76 |
+
2021-03-01,47.16483176312248
|
| 77 |
+
2021-04-01,53.61313888888889
|
| 78 |
+
2021-05-01,53.34893817204301
|
| 79 |
+
2021-06-01,74.07995833333334
|
| 80 |
+
2021-07-01,81.36924731182796
|
| 81 |
+
2021-08-01,82.69688172043011
|
| 82 |
+
2021-09-01,128.37230555555556
|
| 83 |
+
2021-10-01,139.59403225806452
|
| 84 |
+
2021-11-01,176.1513611111111
|
| 85 |
+
2021-12-01,221.06038978494624
|
| 86 |
+
2022-01-01,167.72657258064518
|
| 87 |
+
2022-02-01,128.80267857142857
|
| 88 |
+
2022-03-01,252.00685060565274
|
| 89 |
+
2022-04-01,165.73190277777778
|
| 90 |
+
2022-05-01,177.4769489247312
|
| 91 |
+
2022-06-01,218.0332361111111
|
| 92 |
+
2022-07-01,315.0009946236559
|
| 93 |
+
2022-08-01,465.18350806451616
|
| 94 |
+
2022-09-01,346.11512500000003
|
| 95 |
+
2022-10-01,152.67469086021507
|
| 96 |
+
2022-11-01,173.634375
|
| 97 |
+
2022-12-01,251.61639784946237
|
| 98 |
+
2023-01-01,117.82931451612903
|
| 99 |
+
2023-02-01,128.31184523809523
|
| 100 |
+
2023-03-01,102.5214535666218
|
| 101 |
+
2023-04-01,100.74399999999999
|
| 102 |
+
2023-05-01,81.71538978494624
|
| 103 |
+
2023-06-01,94.7561111111111
|
| 104 |
+
2023-07-01,77.6061559139785
|
| 105 |
+
2023-08-01,94.3218817204301
|
| 106 |
+
2023-09-01,100.72348611111111
|
| 107 |
+
2023-10-01,87.49303763440861
|
| 108 |
+
2023-11-01,91.12227777777777
|
| 109 |
+
2023-12-01,68.51932795698924
|
| 110 |
+
2024-01-01,76.57114247311829
|
| 111 |
+
2024-02-01,61.335847701149426
|
| 112 |
+
2024-03-01,64.70199192462988
|
| 113 |
+
2024-04-01,62.360819444444445
|
| 114 |
+
2024-05-01,67.21001344086021
|
| 115 |
+
2024-06-01,72.88772222222222
|
| 116 |
+
2024-07-01,67.69702956989246
|
| 117 |
+
2024-08-01,82.04717741935484
|
| 118 |
+
2024-09-01,78.30997222222223
|
| 119 |
+
2024-10-01,86.10174731182795
|
| 120 |
+
2024-11-01,113.90644444444445
|
| 121 |
+
2024-12-01,108.31559139784946
|
| 122 |
+
2025-01-01,114.14016129032258
|
| 123 |
+
2025-02-01,128.52236607142856
|
| 124 |
+
2025-03-01,94.72749663526245
|
| 125 |
+
2025-04-01,77.93565277777778
|
| 126 |
+
2025-05-01,67.33862903225807
|
| 127 |
+
2025-06-01,63.9875
|
| 128 |
+
2025-07-01,87.79522849462366
|
| 129 |
+
2025-08-01,76.99025537634408
|
| 130 |
+
2025-09-01,83.51108333333333
|
| 131 |
+
2025-10-01,84.51182795698925
|
| 132 |
+
2025-11-01,101.88231944444445
|
| 133 |
+
2025-12-01,93.47024193548387
|