openenergyid 0.1.18__py2.py3-none-any.whl → 0.1.20__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of openenergyid might be problematic. Click here for more details.
- openenergyid/__init__.py +1 -1
- openenergyid/dyntar/__init__.py +4 -1
- openenergyid/dyntar/const.py +9 -0
- openenergyid/dyntar/main.py +202 -177
- openenergyid/dyntar/models.py +40 -3
- {openenergyid-0.1.18.dist-info → openenergyid-0.1.20.dist-info}/METADATA +1 -1
- {openenergyid-0.1.18.dist-info → openenergyid-0.1.20.dist-info}/RECORD +9 -9
- {openenergyid-0.1.18.dist-info → openenergyid-0.1.20.dist-info}/WHEEL +0 -0
- {openenergyid-0.1.18.dist-info → openenergyid-0.1.20.dist-info}/licenses/LICENSE +0 -0
openenergyid/__init__.py
CHANGED
openenergyid/dyntar/__init__.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Dynamic Tariff Analysis module."""
|
|
2
2
|
|
|
3
|
-
from .main import calculate_dyntar_columns
|
|
3
|
+
from .main import calculate_dyntar_columns, summarize_result
|
|
4
4
|
from .models import (
|
|
5
5
|
DynamicTariffAnalysisInput,
|
|
6
6
|
DynamicTariffAnalysisOutput,
|
|
7
|
+
DynamicTariffAnalysisOutputSummary,
|
|
7
8
|
OutputColumns,
|
|
8
9
|
RequiredColumns,
|
|
9
10
|
)
|
|
@@ -12,6 +13,8 @@ __all__ = [
|
|
|
12
13
|
"calculate_dyntar_columns",
|
|
13
14
|
"DynamicTariffAnalysisInput",
|
|
14
15
|
"DynamicTariffAnalysisOutput",
|
|
16
|
+
"DynamicTariffAnalysisOutputSummary",
|
|
15
17
|
"OutputColumns",
|
|
16
18
|
"RequiredColumns",
|
|
19
|
+
"summarize_result",
|
|
17
20
|
]
|
openenergyid/dyntar/const.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Constants for the dyntar analysis."""
|
|
2
2
|
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
3
5
|
ELECTRICITY_DELIVERED_SMR3 = "electricity_delivered_smr3"
|
|
4
6
|
ELECTRICITY_EXPORTED_SMR3 = "electricity_exported_smr3"
|
|
5
7
|
ELECTRICITY_DELIVERED_SMR2 = "electricity_delivered_smr2"
|
|
@@ -20,3 +22,10 @@ HEATMAP_TOTAL = "heatmap_total"
|
|
|
20
22
|
HEATMAP_DELIVERED_DESCRIPTION = "heatmap_delivered_description"
|
|
21
23
|
HEATMAP_EXPORTED_DESCRIPTION = "heatmap_exported_description"
|
|
22
24
|
HEATMAP_TOTAL_DESCRIPTION = "heatmap_total_description"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Register(Enum):
|
|
28
|
+
"""Register for dynamic tariff analysis."""
|
|
29
|
+
|
|
30
|
+
DELIVERY = "delivery"
|
|
31
|
+
EXPORT = "export"
|
openenergyid/dyntar/main.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Main module of the DynTar package."""
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
from typing import cast
|
|
4
4
|
import pandas as pd
|
|
5
5
|
|
|
6
6
|
from openenergyid.const import (
|
|
@@ -29,33 +29,40 @@ from .const import (
|
|
|
29
29
|
HEATMAP_DELIVERED_DESCRIPTION,
|
|
30
30
|
HEATMAP_EXPORTED_DESCRIPTION,
|
|
31
31
|
HEATMAP_TOTAL_DESCRIPTION,
|
|
32
|
+
Register,
|
|
32
33
|
)
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
def weigh_by_monthly_profile(
|
|
36
|
+
def weigh_by_monthly_profile(df: pd.DataFrame, series_name, profile_name) -> pd.Series:
|
|
36
37
|
"""Weigh a time series by a monthly profile."""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
frame["weighted"] = frame["series"].sum() * (frame["profile"] / frame["profile"].sum())
|
|
42
|
-
results.append(frame)
|
|
43
|
-
return pd.concat(results)["weighted"]
|
|
38
|
+
grouped = df.groupby(pd.Grouper(freq="MS"))
|
|
39
|
+
return grouped[series_name].transform("sum") * grouped[profile_name].transform(
|
|
40
|
+
lambda x: x / x.sum()
|
|
41
|
+
)
|
|
44
42
|
|
|
45
43
|
|
|
46
|
-
def extend_dataframe_with_smr2(
|
|
44
|
+
def extend_dataframe_with_smr2(
|
|
45
|
+
df: pd.DataFrame,
|
|
46
|
+
inplace: bool = False,
|
|
47
|
+
registers: list[Register] | None = None,
|
|
48
|
+
) -> pd.DataFrame | None:
|
|
47
49
|
"""Extend a DataFrame with the SMR2 columns."""
|
|
48
50
|
if not inplace:
|
|
49
51
|
result_df = df.copy()
|
|
50
52
|
else:
|
|
51
53
|
result_df = df
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
if registers is None:
|
|
56
|
+
registers = [Register.DELIVERY, Register.EXPORT]
|
|
57
|
+
|
|
58
|
+
if Register.DELIVERY in registers:
|
|
59
|
+
result_df[ELECTRICITY_DELIVERED_SMR2] = weigh_by_monthly_profile(
|
|
60
|
+
df, ELECTRICITY_DELIVERED, RLP
|
|
61
|
+
)
|
|
62
|
+
if Register.EXPORT in registers:
|
|
63
|
+
result_df[ELECTRICITY_EXPORTED_SMR2] = weigh_by_monthly_profile(
|
|
64
|
+
df, ELECTRICITY_EXPORTED, SPP
|
|
65
|
+
)
|
|
59
66
|
|
|
60
67
|
result_df.rename(
|
|
61
68
|
columns={
|
|
@@ -63,6 +70,7 @@ def extend_dataframe_with_smr2(df: pd.DataFrame, inplace: bool = False) -> pd.Da
|
|
|
63
70
|
ELECTRICITY_EXPORTED: ELECTRICITY_EXPORTED_SMR3,
|
|
64
71
|
},
|
|
65
72
|
inplace=True,
|
|
73
|
+
errors="ignore",
|
|
66
74
|
)
|
|
67
75
|
|
|
68
76
|
if not inplace:
|
|
@@ -70,26 +78,33 @@ def extend_dataframe_with_smr2(df: pd.DataFrame, inplace: bool = False) -> pd.Da
|
|
|
70
78
|
return None
|
|
71
79
|
|
|
72
80
|
|
|
73
|
-
def extend_dataframe_with_costs(
|
|
81
|
+
def extend_dataframe_with_costs(
|
|
82
|
+
df: pd.DataFrame, inplace: bool = False, registers: list[Register] | None = None
|
|
83
|
+
) -> pd.DataFrame | None:
|
|
74
84
|
"""Extend a DataFrame with the cost columns."""
|
|
75
85
|
if not inplace:
|
|
76
86
|
result_df = df.copy()
|
|
77
87
|
else:
|
|
78
88
|
result_df = df
|
|
79
89
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
if registers is None:
|
|
91
|
+
registers = [Register.DELIVERY, Register.EXPORT]
|
|
92
|
+
|
|
93
|
+
if Register.DELIVERY in registers:
|
|
94
|
+
result_df[COST_ELECTRICITY_DELIVERED_SMR2] = (
|
|
95
|
+
df[ELECTRICITY_DELIVERED_SMR2] * df[PRICE_ELECTRICITY_DELIVERED]
|
|
96
|
+
)
|
|
97
|
+
result_df[COST_ELECTRICITY_DELIVERED_SMR3] = (
|
|
98
|
+
df[ELECTRICITY_DELIVERED_SMR3] * df[PRICE_ELECTRICITY_DELIVERED]
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
if Register.EXPORT in registers:
|
|
102
|
+
result_df[COST_ELECTRICITY_EXPORTED_SMR2] = (
|
|
103
|
+
df[ELECTRICITY_EXPORTED_SMR2] * df[PRICE_ELECTRICITY_EXPORTED] * -1
|
|
104
|
+
)
|
|
105
|
+
result_df[COST_ELECTRICITY_EXPORTED_SMR3] = (
|
|
106
|
+
df[ELECTRICITY_EXPORTED_SMR3] * df[PRICE_ELECTRICITY_EXPORTED] * -1
|
|
107
|
+
)
|
|
93
108
|
|
|
94
109
|
if not inplace:
|
|
95
110
|
return result_df
|
|
@@ -97,63 +112,70 @@ def extend_dataframe_with_costs(df: pd.DataFrame, inplace: bool = False) -> pd.D
|
|
|
97
112
|
|
|
98
113
|
|
|
99
114
|
def extend_dataframe_with_weighted_prices(
|
|
100
|
-
df: pd.DataFrame, inplace: bool = False
|
|
115
|
+
df: pd.DataFrame, inplace: bool = False, registers: list[Register] | None = None
|
|
101
116
|
) -> pd.DataFrame | None:
|
|
102
117
|
"""Extend a DataFrame with the weighted price columns."""
|
|
103
118
|
if not inplace:
|
|
104
119
|
df = df.copy()
|
|
105
120
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
df[RLP]
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
if registers is None:
|
|
122
|
+
registers = [Register.DELIVERY, Register.EXPORT]
|
|
123
|
+
|
|
124
|
+
if Register.DELIVERY in registers:
|
|
125
|
+
rlp_weighted_price_delivered = (df[PRICE_ELECTRICITY_DELIVERED] * df[RLP]).resample(
|
|
126
|
+
"MS"
|
|
127
|
+
).sum() / df[RLP].resample("MS").sum()
|
|
128
|
+
df[RLP_WEIGHTED_PRICE_DELIVERED] = rlp_weighted_price_delivered.reindex_like(
|
|
129
|
+
df[RLP], method="ffill"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
if Register.EXPORT in registers:
|
|
133
|
+
spp_weighted_price_exported = (df[PRICE_ELECTRICITY_EXPORTED] * df[SPP]).resample(
|
|
134
|
+
"MS"
|
|
135
|
+
).sum() / df[SPP].resample("MS").sum()
|
|
136
|
+
df[SPP_WEIGHTED_PRICE_EXPORTED] = spp_weighted_price_exported.reindex_like(
|
|
137
|
+
df[SPP], method="ffill"
|
|
138
|
+
)
|
|
118
139
|
|
|
119
140
|
if not inplace:
|
|
120
141
|
return df
|
|
121
142
|
return None
|
|
122
143
|
|
|
123
144
|
|
|
124
|
-
def extend_dataframe_with_heatmap(
|
|
145
|
+
def extend_dataframe_with_heatmap(
|
|
146
|
+
df: pd.DataFrame, inplace: bool = False, registers: list[Register] | None = None
|
|
147
|
+
) -> pd.DataFrame | None:
|
|
125
148
|
"""Extend a DataFrame with the heatmap columns."""
|
|
126
149
|
if not inplace:
|
|
127
150
|
df = df.copy()
|
|
128
151
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
df[
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
df[HEATMAP_EXPORTED] = heatmap_score_exported
|
|
152
|
+
if registers is None:
|
|
153
|
+
registers = [Register.DELIVERY, Register.EXPORT]
|
|
154
|
+
|
|
155
|
+
if Register.DELIVERY in registers:
|
|
156
|
+
energy_delta_delivered = df[ELECTRICITY_DELIVERED_SMR2] - df[ELECTRICITY_DELIVERED_SMR3]
|
|
157
|
+
price_delta_delivered = df[RLP_WEIGHTED_PRICE_DELIVERED] - df[PRICE_ELECTRICITY_DELIVERED]
|
|
158
|
+
heatmap_score_delivered = energy_delta_delivered * price_delta_delivered
|
|
159
|
+
heatmap_score_delivered.fillna(0, inplace=True)
|
|
160
|
+
# Invert score so that positive values indicate a positive impact
|
|
161
|
+
heatmap_score_delivered = -heatmap_score_delivered
|
|
162
|
+
df[HEATMAP_DELIVERED] = heatmap_score_delivered
|
|
163
|
+
|
|
164
|
+
if Register.EXPORT in registers:
|
|
165
|
+
energy_delta_exported = df[ELECTRICITY_EXPORTED_SMR2] - df[ELECTRICITY_EXPORTED_SMR3]
|
|
166
|
+
price_delta_exported = df[SPP_WEIGHTED_PRICE_EXPORTED] - df[PRICE_ELECTRICITY_EXPORTED]
|
|
167
|
+
heatmap_score_exported = energy_delta_exported * price_delta_exported
|
|
168
|
+
heatmap_score_exported.fillna(0, inplace=True)
|
|
169
|
+
df[HEATMAP_EXPORTED] = heatmap_score_exported
|
|
170
|
+
|
|
171
|
+
if Register.DELIVERY in registers and Register.EXPORT in registers:
|
|
172
|
+
heatmap_score_delivered = cast(pd.Series, df[HEATMAP_DELIVERED])
|
|
173
|
+
heatmap_score_exported = cast(pd.Series, df[HEATMAP_EXPORTED])
|
|
174
|
+
heatmap_score_combined = heatmap_score_delivered + heatmap_score_exported
|
|
175
|
+
elif Register.DELIVERY in registers:
|
|
176
|
+
heatmap_score_combined = heatmap_score_delivered
|
|
177
|
+
else:
|
|
178
|
+
heatmap_score_combined = heatmap_score_exported
|
|
157
179
|
df[HEATMAP_TOTAL] = heatmap_score_combined
|
|
158
180
|
|
|
159
181
|
if not inplace:
|
|
@@ -161,127 +183,130 @@ def extend_dataframe_with_heatmap(df: pd.DataFrame, inplace: bool = False) -> pd
|
|
|
161
183
|
return None
|
|
162
184
|
|
|
163
185
|
|
|
186
|
+
def map_delivery_description(
|
|
187
|
+
price_delivered, price_rlp, electricity_delivered_smr3, electricity_delivered_smr2
|
|
188
|
+
):
|
|
189
|
+
"""Map the delivery description."""
|
|
190
|
+
if price_delivered > price_rlp and electricity_delivered_smr3 > electricity_delivered_smr2:
|
|
191
|
+
return 1
|
|
192
|
+
if price_delivered > price_rlp and electricity_delivered_smr3 < electricity_delivered_smr2:
|
|
193
|
+
return 2
|
|
194
|
+
if price_delivered < price_rlp and electricity_delivered_smr3 > electricity_delivered_smr2:
|
|
195
|
+
return 3
|
|
196
|
+
if price_delivered < price_rlp and electricity_delivered_smr3 < electricity_delivered_smr2:
|
|
197
|
+
return 4
|
|
198
|
+
return 0
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def map_export_description(
|
|
202
|
+
price_exported, price_spp, electricity_exported_smr3, electricity_exported_smr2
|
|
203
|
+
):
|
|
204
|
+
"""Map the export description."""
|
|
205
|
+
if price_exported > price_spp and electricity_exported_smr3 > electricity_exported_smr2:
|
|
206
|
+
return 5
|
|
207
|
+
if price_exported > price_spp and electricity_exported_smr3 < electricity_exported_smr2:
|
|
208
|
+
return 6
|
|
209
|
+
if price_exported < price_spp and electricity_exported_smr3 > electricity_exported_smr2:
|
|
210
|
+
return 7
|
|
211
|
+
if price_exported < price_spp and electricity_exported_smr3 < electricity_exported_smr2:
|
|
212
|
+
return 8
|
|
213
|
+
return 0
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def map_total_description(
|
|
217
|
+
abs_heatmap_delivered, abs_heatmap_exported, delivered_description, exported_description
|
|
218
|
+
):
|
|
219
|
+
"""Map the total description."""
|
|
220
|
+
if abs_heatmap_delivered > abs_heatmap_exported:
|
|
221
|
+
return delivered_description
|
|
222
|
+
return exported_description
|
|
223
|
+
|
|
224
|
+
|
|
164
225
|
def extend_dataframe_with_heatmap_description(
|
|
165
|
-
df: pd.DataFrame, inplace: bool = False
|
|
226
|
+
df: pd.DataFrame, inplace: bool = False, registers: list[Register] | None = None
|
|
166
227
|
) -> pd.DataFrame | None:
|
|
167
228
|
"""Extend a DataFrame with the heatmap description columns."""
|
|
168
229
|
if not inplace:
|
|
169
230
|
df = df.copy()
|
|
170
231
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
df[HEATMAP_DELIVERED_DESCRIPTION] = df[HEATMAP_DELIVERED_DESCRIPTION].replace(np.nan, 0)
|
|
211
|
-
|
|
212
|
-
# Exported
|
|
213
|
-
|
|
214
|
-
# Where Heatmap is 0, we put a desription of 0 (No impact)
|
|
215
|
-
df[HEATMAP_EXPORTED_DESCRIPTION] = df[HEATMAP_EXPORTED].apply(
|
|
216
|
-
lambda x: 0 if x == 0 else float("NaN")
|
|
217
|
-
)
|
|
218
|
-
# When the energy delta is positive, and the price delta is positive, we put a description of 5 (high injection, high price)
|
|
219
|
-
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
220
|
-
lambda x: 5
|
|
221
|
-
if x[PRICE_ELECTRICITY_EXPORTED] > x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
222
|
-
and x[ELECTRICITY_EXPORTED_SMR3] > x[ELECTRICITY_EXPORTED_SMR2]
|
|
223
|
-
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
224
|
-
axis=1,
|
|
225
|
-
)
|
|
226
|
-
# When the energy delta is negative, and the price delta is positive, we put a description of 6 (low injection, high price)
|
|
227
|
-
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
228
|
-
lambda x: 6
|
|
229
|
-
if x[PRICE_ELECTRICITY_EXPORTED] > x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
230
|
-
and x[ELECTRICITY_EXPORTED_SMR3] < x[ELECTRICITY_EXPORTED_SMR2]
|
|
231
|
-
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
232
|
-
axis=1,
|
|
233
|
-
)
|
|
234
|
-
# When the energy delta is positive, and the price delta is negative, we put a description of 7 (high injection, low price)
|
|
235
|
-
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
236
|
-
lambda x: 7
|
|
237
|
-
if x[PRICE_ELECTRICITY_EXPORTED] < x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
238
|
-
and x[ELECTRICITY_EXPORTED_SMR3] > x[ELECTRICITY_EXPORTED_SMR2]
|
|
239
|
-
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
240
|
-
axis=1,
|
|
241
|
-
)
|
|
242
|
-
# When the energy delta is negative, and the price delta is negative, we put a description of 8 (low injection, low price)
|
|
243
|
-
df[HEATMAP_EXPORTED_DESCRIPTION] = df.apply(
|
|
244
|
-
lambda x: 8
|
|
245
|
-
if x[PRICE_ELECTRICITY_EXPORTED] < x[SPP_WEIGHTED_PRICE_EXPORTED]
|
|
246
|
-
and x[ELECTRICITY_EXPORTED_SMR3] < x[ELECTRICITY_EXPORTED_SMR2]
|
|
247
|
-
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
248
|
-
axis=1,
|
|
249
|
-
)
|
|
250
|
-
# All other cases are put as 0
|
|
251
|
-
df[HEATMAP_EXPORTED_DESCRIPTION] = df[HEATMAP_EXPORTED_DESCRIPTION].replace(np.nan, 0)
|
|
252
|
-
|
|
253
|
-
# Total
|
|
254
|
-
|
|
255
|
-
# We see which of the individual heatmaps has the highest absolute value
|
|
256
|
-
# We put the description of the highest absolute value
|
|
257
|
-
df[HEATMAP_TOTAL_DESCRIPTION] = df.apply(
|
|
258
|
-
lambda x: x[HEATMAP_DELIVERED_DESCRIPTION]
|
|
259
|
-
if abs(x[HEATMAP_DELIVERED]) > abs(x[HEATMAP_EXPORTED])
|
|
260
|
-
else x[HEATMAP_EXPORTED_DESCRIPTION],
|
|
261
|
-
axis=1,
|
|
262
|
-
)
|
|
263
|
-
# Where Heatmap is 0, we put a desription of 0 (No impact)
|
|
264
|
-
df[HEATMAP_TOTAL_DESCRIPTION] = df.apply(
|
|
265
|
-
lambda x: 0 if x[HEATMAP_TOTAL] == 0 else x[HEATMAP_TOTAL_DESCRIPTION], axis=1
|
|
266
|
-
)
|
|
267
|
-
# All other cases are put as 0
|
|
268
|
-
df[HEATMAP_TOTAL_DESCRIPTION] = df[HEATMAP_TOTAL_DESCRIPTION].replace(np.nan, 0)
|
|
232
|
+
if registers is None:
|
|
233
|
+
registers = [Register.DELIVERY, Register.EXPORT]
|
|
234
|
+
|
|
235
|
+
if Register.DELIVERY in registers:
|
|
236
|
+
df[HEATMAP_DELIVERED_DESCRIPTION] = list(
|
|
237
|
+
map(
|
|
238
|
+
map_delivery_description,
|
|
239
|
+
df[PRICE_ELECTRICITY_DELIVERED],
|
|
240
|
+
df[RLP_WEIGHTED_PRICE_DELIVERED],
|
|
241
|
+
df[ELECTRICITY_DELIVERED_SMR3],
|
|
242
|
+
df[ELECTRICITY_DELIVERED_SMR2],
|
|
243
|
+
)
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
if Register.EXPORT in registers:
|
|
247
|
+
df[HEATMAP_EXPORTED_DESCRIPTION] = list(
|
|
248
|
+
map(
|
|
249
|
+
map_export_description,
|
|
250
|
+
df[PRICE_ELECTRICITY_EXPORTED],
|
|
251
|
+
df[SPP_WEIGHTED_PRICE_EXPORTED],
|
|
252
|
+
df[ELECTRICITY_EXPORTED_SMR3],
|
|
253
|
+
df[ELECTRICITY_EXPORTED_SMR2],
|
|
254
|
+
)
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
if Register.DELIVERY in registers and Register.EXPORT in registers:
|
|
258
|
+
df[HEATMAP_TOTAL_DESCRIPTION] = list(
|
|
259
|
+
map(
|
|
260
|
+
map_total_description,
|
|
261
|
+
df[HEATMAP_DELIVERED].abs(),
|
|
262
|
+
df[HEATMAP_EXPORTED].abs(),
|
|
263
|
+
df[HEATMAP_DELIVERED_DESCRIPTION],
|
|
264
|
+
df[HEATMAP_EXPORTED_DESCRIPTION],
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
elif Register.DELIVERY in registers:
|
|
268
|
+
df[HEATMAP_TOTAL_DESCRIPTION] = df[HEATMAP_DELIVERED_DESCRIPTION]
|
|
269
|
+
else:
|
|
270
|
+
df[HEATMAP_TOTAL_DESCRIPTION] = df[HEATMAP_EXPORTED_DESCRIPTION]
|
|
269
271
|
|
|
270
272
|
if not inplace:
|
|
271
273
|
return df
|
|
272
274
|
|
|
273
275
|
|
|
274
|
-
def calculate_dyntar_columns(
|
|
276
|
+
def calculate_dyntar_columns(
|
|
277
|
+
df: pd.DataFrame,
|
|
278
|
+
inplace: bool = False,
|
|
279
|
+
registers: list[Register] | None = None,
|
|
280
|
+
) -> pd.DataFrame | None:
|
|
275
281
|
"""Calculate all columns required for the dynamic tariff analysis."""
|
|
276
282
|
if not inplace:
|
|
277
283
|
df = df.copy()
|
|
278
284
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
285
|
+
if registers is None:
|
|
286
|
+
registers = [Register.DELIVERY, Register.EXPORT]
|
|
287
|
+
|
|
288
|
+
extend_dataframe_with_smr2(df, inplace=True, registers=registers)
|
|
289
|
+
extend_dataframe_with_costs(df, inplace=True, registers=registers)
|
|
290
|
+
extend_dataframe_with_weighted_prices(df, inplace=True, registers=registers)
|
|
291
|
+
extend_dataframe_with_heatmap(df, inplace=True, registers=registers)
|
|
292
|
+
extend_dataframe_with_heatmap_description(df, inplace=True, registers=registers)
|
|
284
293
|
|
|
285
294
|
if not inplace:
|
|
286
295
|
return df
|
|
287
296
|
return None
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def summarize_result(df: pd.DataFrame) -> pd.Series:
|
|
300
|
+
"""Summarize the dynamic tariff analysis result."""
|
|
301
|
+
summary = df.filter(like="cost").sum()
|
|
302
|
+
|
|
303
|
+
abs_smr2 = summary.filter(like="smr2").abs().sum()
|
|
304
|
+
|
|
305
|
+
summary["cost_electricity_total_smr2"] = summary.filter(like="smr2").sum()
|
|
306
|
+
summary["cost_electricity_total_smr3"] = summary.filter(like="smr3").sum()
|
|
307
|
+
|
|
308
|
+
summary["ratio"] = (
|
|
309
|
+
summary["cost_electricity_total_smr3"] - summary["cost_electricity_total_smr2"]
|
|
310
|
+
) / abs_smr2
|
|
311
|
+
|
|
312
|
+
return summary
|
openenergyid/dyntar/models.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Models for dynamic tariff analysis."""
|
|
2
2
|
|
|
3
3
|
from typing import Literal
|
|
4
|
-
from pydantic import Field, conlist, confloat
|
|
4
|
+
from pydantic import Field, conlist, confloat, BaseModel
|
|
5
5
|
|
|
6
6
|
from openenergyid.models import TimeDataFrame
|
|
7
|
+
from .const import Register
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
RequiredColumns = Literal[
|
|
@@ -43,18 +44,53 @@ class DynamicTariffAnalysisInput(TimeDataFrame):
|
|
|
43
44
|
"""Input frame for dynamic tariff analysis."""
|
|
44
45
|
|
|
45
46
|
columns: list[RequiredColumns] = Field(
|
|
46
|
-
min_length=
|
|
47
|
+
min_length=3,
|
|
47
48
|
max_length=len(RequiredColumns.__args__),
|
|
48
49
|
examples=[RequiredColumns.__args__],
|
|
49
50
|
)
|
|
50
51
|
data: list[
|
|
51
52
|
conlist(
|
|
52
53
|
item_type=confloat(allow_inf_nan=True),
|
|
53
|
-
min_length=
|
|
54
|
+
min_length=3,
|
|
54
55
|
max_length=len(RequiredColumns.__args__),
|
|
55
56
|
) # type: ignore
|
|
56
57
|
] = Field(examples=[[0.0] * len(RequiredColumns.__args__)])
|
|
57
58
|
|
|
59
|
+
@property
|
|
60
|
+
def registers(self) -> list[Register]:
|
|
61
|
+
"""Check which registers are present in the input data."""
|
|
62
|
+
registers = []
|
|
63
|
+
columns = list(self.columns)
|
|
64
|
+
# if "electricity_delivered", "price_electricity_delivered" and "RLP" are present
|
|
65
|
+
if all(
|
|
66
|
+
column in columns
|
|
67
|
+
for column in [
|
|
68
|
+
"electricity_delivered",
|
|
69
|
+
"price_electricity_delivered",
|
|
70
|
+
"RLP",
|
|
71
|
+
]
|
|
72
|
+
):
|
|
73
|
+
registers.append(Register.DELIVERY)
|
|
74
|
+
# if "electricity_exported", "price_electricity_exported" and "SPP" are present
|
|
75
|
+
if all(
|
|
76
|
+
column in columns
|
|
77
|
+
for column in ["electricity_exported", "price_electricity_exported", "SPP"]
|
|
78
|
+
):
|
|
79
|
+
registers.append(Register.EXPORT)
|
|
80
|
+
return registers
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class DynamicTariffAnalysisOutputSummary(BaseModel):
|
|
84
|
+
"""Summary of the dynamic tariff analysis output."""
|
|
85
|
+
|
|
86
|
+
cost_electricity_delivered_smr2: float | None = None
|
|
87
|
+
cost_electricity_delivered_smr3: float | None = None
|
|
88
|
+
cost_electricity_exported_smr2: float | None = None
|
|
89
|
+
cost_electricity_exported_smr3: float | None = None
|
|
90
|
+
cost_electricity_total_smr2: float | None = None
|
|
91
|
+
cost_electricity_total_smr3: float | None = None
|
|
92
|
+
ratio: float | None = None
|
|
93
|
+
|
|
58
94
|
|
|
59
95
|
class DynamicTariffAnalysisOutput(TimeDataFrame):
|
|
60
96
|
"""Output frame for dynamic tariff analysis."""
|
|
@@ -71,3 +107,4 @@ class DynamicTariffAnalysisOutput(TimeDataFrame):
|
|
|
71
107
|
max_length=len(OutputColumns.__args__),
|
|
72
108
|
) # type: ignore
|
|
73
109
|
] = Field(examples=[[0.0] * len(OutputColumns.__args__)])
|
|
110
|
+
summary: DynamicTariffAnalysisOutputSummary | None = None
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
openenergyid/__init__.py,sha256=
|
|
1
|
+
openenergyid/__init__.py,sha256=XVOYN9RAdcNJV1DaB0k2pD_zyPnk2aF6D5Tk4HFt4TU,193
|
|
2
2
|
openenergyid/const.py,sha256=D-xUnUyVuLmphClkePgxpFP6z0RDhw_6m7rX0BHBgrw,823
|
|
3
3
|
openenergyid/enums.py,sha256=jdw4CB1gkisx0re_SesrTEyh_T-UxYp6uieE7iYlHdA,357
|
|
4
4
|
openenergyid/models.py,sha256=CO6VdthCOQ9hNXqVSan_4IOBpiQvOix-ea3U6TR7Vgc,4343
|
|
5
5
|
openenergyid/capacity/__init__.py,sha256=1En96HlPV8kd1hOJO9RjRbXNInp5ZSkmjsjp0jfZlcQ,221
|
|
6
6
|
openenergyid/capacity/main.py,sha256=G6_EtXs1k_W-fxS33pFrCNKajuH81skdI32zp5RX9bI,3674
|
|
7
7
|
openenergyid/capacity/models.py,sha256=qi0IFyF_QOVleSzN8g0U2Fzqcc9ZDfNKt8oteFLY6Q0,832
|
|
8
|
-
openenergyid/dyntar/__init__.py,sha256=
|
|
9
|
-
openenergyid/dyntar/const.py,sha256=
|
|
10
|
-
openenergyid/dyntar/main.py,sha256=
|
|
11
|
-
openenergyid/dyntar/models.py,sha256=
|
|
8
|
+
openenergyid/dyntar/__init__.py,sha256=lUrk7ktS7yAqiafRHFoBE0RvFSI9mzDoO37diwLHuBg,495
|
|
9
|
+
openenergyid/dyntar/const.py,sha256=eJJV9VfpHlS9vWV47DWQkS3ICIXWhDmG4cU-ofbZJ3Q,1100
|
|
10
|
+
openenergyid/dyntar/main.py,sha256=i8EkayRicnMhG66cyrxGwUumFx3UGe7KDSImfFqmK04,10638
|
|
11
|
+
openenergyid/dyntar/models.py,sha256=lI4IjdAFallhsCqbw-EbBPbmk0g2MACgZnmMtTX7Pq0,3452
|
|
12
12
|
openenergyid/energysharing/__init__.py,sha256=A4JfrUYf-hBCzhUm0qL1GGlNMvpO8OwXJo80dJxFIvw,274
|
|
13
13
|
openenergyid/energysharing/const.py,sha256=X2zEPtTlsmZ66w6RmLS_h8NmdzObAEi5N6-0yrLN5V4,219
|
|
14
14
|
openenergyid/energysharing/data_formatting.py,sha256=Kwuhyn6ao_8Brdm9frlA6VzYOqimNYZsRbYwNXnE7yc,2583
|
|
@@ -19,7 +19,7 @@ openenergyid/mvlr/helpers.py,sha256=Uzbfrj3IpH26wA206KOl0hNucKE-n9guJNC_EROBVKA,
|
|
|
19
19
|
openenergyid/mvlr/main.py,sha256=cn7jZ98cHn2eh-0zG9q8Pad0Ft_FuI-u3a-eeHeF8jA,1304
|
|
20
20
|
openenergyid/mvlr/models.py,sha256=XvkViOLlYqi0ffgF3AD4Jvk3yL05gsoKdKgBAsGJ7L4,8581
|
|
21
21
|
openenergyid/mvlr/mvlr.py,sha256=F7WvWnZQtqUmK1vsguemsn9n8pDDk3tQ1weOlv-bo0c,18626
|
|
22
|
-
openenergyid-0.1.
|
|
23
|
-
openenergyid-0.1.
|
|
24
|
-
openenergyid-0.1.
|
|
25
|
-
openenergyid-0.1.
|
|
22
|
+
openenergyid-0.1.20.dist-info/METADATA,sha256=UJ-vbPX22VRhTyEtFnf0XzxrQa-U2LbdocBPcUFucuo,2477
|
|
23
|
+
openenergyid-0.1.20.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
|
|
24
|
+
openenergyid-0.1.20.dist-info/licenses/LICENSE,sha256=NgRdcNHwyXVCXZ8sJwoTp0DCowThJ9LWWl4xhbV1IUY,1074
|
|
25
|
+
openenergyid-0.1.20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|