detquantlib 2.1.1__tar.gz → 3.0.0__tar.gz
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.
- {detquantlib-2.1.1 → detquantlib-3.0.0}/PKG-INFO +1 -1
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/data/databases/detdatabase.py +188 -72
- {detquantlib-2.1.1 → detquantlib-3.0.0}/pyproject.toml +1 -1
- {detquantlib-2.1.1 → detquantlib-3.0.0}/LICENSE.txt +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/README.md +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/__init__.py +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/data/entsoe/entsoe.py +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/data/sftp/sftp.py +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/dates/dates.py +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/figures/plotly_figures.py +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/stats/data_analysis.py +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/tradable_products/tradable_products.py +0 -0
- {detquantlib-2.1.1 → detquantlib-3.0.0}/detquantlib/utils/utils.py +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Python built-in packages
|
|
2
|
+
import os
|
|
2
3
|
import warnings
|
|
3
4
|
from datetime import datetime
|
|
4
5
|
from zoneinfo import ZoneInfo
|
|
@@ -16,42 +17,55 @@ class DetDatabase:
|
|
|
16
17
|
|
|
17
18
|
def __init__(
|
|
18
19
|
self,
|
|
19
|
-
username: str,
|
|
20
|
-
password: str,
|
|
21
|
-
server: str,
|
|
22
|
-
database: str,
|
|
23
20
|
connection: pyodbc.Connection = None,
|
|
21
|
+
driver: str = "{ODBC Driver 18 for SQL Server}",
|
|
24
22
|
):
|
|
25
23
|
"""
|
|
26
24
|
Constructor method.
|
|
27
25
|
|
|
28
26
|
Args:
|
|
29
|
-
username: Database username
|
|
30
|
-
password: Database password
|
|
31
|
-
server: Database server name
|
|
32
|
-
database: Database name
|
|
33
27
|
connection: Database connection object. This argument does not have to be passed
|
|
34
28
|
when creating the object. It can be set after the object has been created, using
|
|
35
29
|
the open_connection() method.
|
|
30
|
+
driver: ODBC driver
|
|
31
|
+
|
|
32
|
+
Raises:
|
|
33
|
+
EnvironmentError: Raises an error if environment variables are not defined
|
|
36
34
|
"""
|
|
37
|
-
self.username = username
|
|
38
|
-
self.password = password
|
|
39
|
-
self.server = server
|
|
40
|
-
self.database = database
|
|
41
35
|
self.connection = connection
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
self.driver = driver
|
|
37
|
+
|
|
38
|
+
# Check if environment variables needed by the class are defined
|
|
39
|
+
required_env_vars = [
|
|
40
|
+
dict(name="DET_DB_NAME", value=None, description="DET database name"),
|
|
41
|
+
dict(name="DET_DB_SERVER", value=None, description="DET database server name"),
|
|
42
|
+
dict(
|
|
43
|
+
name="DET_DB_USERNAME", value=None, description="Username to connect to database"
|
|
44
|
+
),
|
|
45
|
+
dict(
|
|
46
|
+
name="DET_DB_PASSWORD", value=None, description="Password to connect to database"
|
|
47
|
+
),
|
|
48
|
+
]
|
|
49
|
+
available_env_vars = os.environ
|
|
50
|
+
for d in required_env_vars:
|
|
51
|
+
if d["name"] not in available_env_vars:
|
|
52
|
+
required_env_vars_names = [x["name"] for x in required_env_vars]
|
|
53
|
+
required_env_vars_str = ", ".join(f"'{x}'" for x in required_env_vars_names)
|
|
54
|
+
raise EnvironmentError(
|
|
55
|
+
f"The DetDatabase class requires the following environment variables: "
|
|
56
|
+
f"{required_env_vars_str}. Environment variable '{d['name']}' "
|
|
57
|
+
f"(description: '{d['description']}') not found."
|
|
58
|
+
)
|
|
45
59
|
|
|
46
60
|
def open_connection(self):
|
|
47
61
|
"""Opens a connection to the database."""
|
|
48
62
|
# Create the connection string
|
|
49
63
|
connection_str = (
|
|
50
64
|
f"DRIVER={self.driver};"
|
|
51
|
-
f"SERVER={
|
|
52
|
-
f"DATABASE={
|
|
53
|
-
f"UID={
|
|
54
|
-
f"PWD={
|
|
65
|
+
f"SERVER={os.getenv('DET_DB_SERVER')};"
|
|
66
|
+
f"DATABASE={os.getenv('DET_DB_NAME')};"
|
|
67
|
+
f"UID={os.getenv('DET_DB_USERNAME')};"
|
|
68
|
+
f"PWD={os.getenv('DET_DB_PASSWORD')}"
|
|
55
69
|
)
|
|
56
70
|
self.connection = pyodbc.connect(connection_str)
|
|
57
71
|
|
|
@@ -88,8 +102,7 @@ class DetDatabase:
|
|
|
88
102
|
|
|
89
103
|
def load_entsoe_day_ahead_spot_prices(
|
|
90
104
|
self,
|
|
91
|
-
|
|
92
|
-
timezone: str,
|
|
105
|
+
commodity_name: str,
|
|
93
106
|
start_trading_date: datetime = None,
|
|
94
107
|
end_trading_date: datetime = None,
|
|
95
108
|
start_delivery_date: datetime = None,
|
|
@@ -101,7 +114,7 @@ class DetDatabase:
|
|
|
101
114
|
Loads entsoe day-ahead spot prices from the database.
|
|
102
115
|
|
|
103
116
|
Args:
|
|
104
|
-
|
|
117
|
+
commodity_name: Commodity name (as defined in the [META].[Commodity] database table)
|
|
105
118
|
start_trading_date: Start trading date
|
|
106
119
|
end_trading_date: End trading date
|
|
107
120
|
Note: The user should provide either 'start_trading_date' and 'end_trading_date',
|
|
@@ -112,9 +125,6 @@ class DetDatabase:
|
|
|
112
125
|
(i.e. delivery dates < end_date).
|
|
113
126
|
Note: The user should provide either 'start_trading_date' and 'end_trading_date',
|
|
114
127
|
or 'start_delivery_date' and 'end_delivery_date'.
|
|
115
|
-
timezone: Timezone of the power country/region. This argument is important because
|
|
116
|
-
ENTSOE provides all prices in the UTC timezone. We first convert the dates from
|
|
117
|
-
UTC to the local timezone, and then filter for the requested delivery period.
|
|
118
128
|
columns: Requested database table columns. Set columns=["*"] (i.e. as list) to get
|
|
119
129
|
all columns.
|
|
120
130
|
process_data: Indicates if data should be processed convert to standardized format
|
|
@@ -123,10 +133,13 @@ class DetDatabase:
|
|
|
123
133
|
Dataframe containing day-ahead spot prices
|
|
124
134
|
|
|
125
135
|
Raises:
|
|
126
|
-
ValueError: Raises an error
|
|
127
|
-
|
|
128
|
-
ValueError: Raises an error
|
|
136
|
+
ValueError: Raises an error if input arguments 'columns' and 'process_data' are not
|
|
137
|
+
compatible
|
|
138
|
+
ValueError: Raises an error if the combination of trading dates and delivery dates
|
|
129
139
|
is not valid.
|
|
140
|
+
ValueError: Raises an error if match with input commodity name is not unique
|
|
141
|
+
ValueError: Raises an error if input commodity is not supported
|
|
142
|
+
ValueError: Raises an error if no price data is found for user inputs
|
|
130
143
|
"""
|
|
131
144
|
# Input validation
|
|
132
145
|
if process_data and columns is not None:
|
|
@@ -164,6 +177,26 @@ class DetDatabase:
|
|
|
164
177
|
else:
|
|
165
178
|
columns_str = f"[{'], ['.join(columns)}]"
|
|
166
179
|
|
|
180
|
+
# Get commodity information (map code and local timezone)
|
|
181
|
+
# Note: The local timezone is important because ENTSOE provides all prices in the UTC
|
|
182
|
+
# timezone. We first convert the dates from UTC to the local timezone, and then filter
|
|
183
|
+
# for the requested delivery period.
|
|
184
|
+
commodity_info = self.load_commodities(
|
|
185
|
+
columns=["Timezone", "EntsoeMapCode"], conditions=f"WHERE Name='{commodity_name}'"
|
|
186
|
+
)
|
|
187
|
+
if commodity_info.shape[0] > 1:
|
|
188
|
+
raise ValueError(f"More than one match found with commodity '{commodity_name}'.")
|
|
189
|
+
elif commodity_info.shape[0] == 0:
|
|
190
|
+
supported_commodities = self.load_commodities(columns=["Name"])
|
|
191
|
+
supported_commodities_str = ", ".join(f"'{x}'" for x in supported_commodities["Name"])
|
|
192
|
+
raise ValueError(
|
|
193
|
+
f"Commodity '{commodity_name}' is not supported. Supported commodities: "
|
|
194
|
+
f"{supported_commodities_str}."
|
|
195
|
+
)
|
|
196
|
+
else:
|
|
197
|
+
map_code = commodity_info.loc[0, "EntsoeMapCode"]
|
|
198
|
+
timezone = commodity_info.loc[0, "Timezone"]
|
|
199
|
+
|
|
167
200
|
# Convert start trading date to start delivery date
|
|
168
201
|
if start_trading_date is not None:
|
|
169
202
|
start_trading_date = pd.Timestamp(start_trading_date).floor("D")
|
|
@@ -198,6 +231,9 @@ class DetDatabase:
|
|
|
198
231
|
df = self.query_db(query)
|
|
199
232
|
self.close_connection()
|
|
200
233
|
|
|
234
|
+
if df.empty:
|
|
235
|
+
raise ValueError("No price data found for user-defined inputs.")
|
|
236
|
+
|
|
201
237
|
# Sort data by delivery date
|
|
202
238
|
df.sort_values(
|
|
203
239
|
by=["DateTime(UTC)"], axis=0, ascending=True, inplace=True, ignore_index=True
|
|
@@ -211,40 +247,30 @@ class DetDatabase:
|
|
|
211
247
|
|
|
212
248
|
# Process raw data and convert it to standardized format
|
|
213
249
|
if process_data:
|
|
214
|
-
df = DetDatabase.process_day_ahead_spot_prices(df, timezone)
|
|
250
|
+
df = DetDatabase.process_day_ahead_spot_prices(df, commodity_name, timezone)
|
|
215
251
|
|
|
216
252
|
return df
|
|
217
253
|
|
|
218
254
|
@staticmethod
|
|
219
|
-
def process_day_ahead_spot_prices(
|
|
255
|
+
def process_day_ahead_spot_prices(
|
|
256
|
+
df_in: pd.DataFrame, commodity_name: str, timezone: str
|
|
257
|
+
) -> pd.DataFrame:
|
|
220
258
|
"""
|
|
221
259
|
Processes day-ahead spot prices and converts from ENTSOE format to standardized format.
|
|
222
260
|
|
|
223
261
|
Args:
|
|
224
262
|
df_in: Dataframe containing day-ahead spot prices
|
|
263
|
+
commodity_name: Commodity name (as defined in the [META].[Commodity] database table)
|
|
225
264
|
timezone: Timezone of the power country/region
|
|
226
265
|
|
|
227
266
|
Returns:
|
|
228
267
|
Processed dataframe containing day-ahead spot prices
|
|
229
268
|
"""
|
|
230
|
-
map_code_to_commodity_mapper = dict(
|
|
231
|
-
NL={"commodity_name": "DutchPower", "product_code": "Q0B"}
|
|
232
|
-
)
|
|
233
|
-
|
|
234
269
|
# Initialize output dataframe
|
|
235
270
|
df_out = pd.DataFrame()
|
|
236
271
|
|
|
237
272
|
# Set commodity name
|
|
238
|
-
|
|
239
|
-
map_code_to_commodity_mapper[mc]["commodity_name"] for mc in df_in["MapCode"]
|
|
240
|
-
]
|
|
241
|
-
df_out["CommodityName"] = commodity_name
|
|
242
|
-
|
|
243
|
-
# Set product code
|
|
244
|
-
product_code = [
|
|
245
|
-
map_code_to_commodity_mapper[mc]["product_code"] for mc in df_in["MapCode"]
|
|
246
|
-
]
|
|
247
|
-
df_out["ProductCode"] = product_code
|
|
273
|
+
df_out["CommodityName"] = [commodity_name] * df_in.shape[0]
|
|
248
274
|
|
|
249
275
|
# Set trading date
|
|
250
276
|
trading_date = [d - relativedelta(days=1, hour=0) for d in df_in[f"DateTime({timezone})"]]
|
|
@@ -267,8 +293,7 @@ class DetDatabase:
|
|
|
267
293
|
|
|
268
294
|
def load_entsoe_imbalance_prices(
|
|
269
295
|
self,
|
|
270
|
-
|
|
271
|
-
timezone: str,
|
|
296
|
+
commodity_name: str,
|
|
272
297
|
start_trading_date: datetime = None,
|
|
273
298
|
end_trading_date: datetime = None,
|
|
274
299
|
start_delivery_date: datetime = None,
|
|
@@ -280,10 +305,7 @@ class DetDatabase:
|
|
|
280
305
|
Loads entsoe imbalance prices from the database.
|
|
281
306
|
|
|
282
307
|
Args:
|
|
283
|
-
|
|
284
|
-
timezone: Timezone of the power country/region. This argument is important because
|
|
285
|
-
ENTSOE provides all prices in the UTC timezone. We first convert the dates from
|
|
286
|
-
UTC to the local timezone, and then filter for the requested delivery period.
|
|
308
|
+
commodity_name: Commodity name (as defined in the [META].[Commodity] database table)
|
|
287
309
|
start_trading_date: Start trading date
|
|
288
310
|
end_trading_date: End trading date
|
|
289
311
|
Note: The user should provide either 'start_trading_date' and 'end_trading_date',
|
|
@@ -302,10 +324,13 @@ class DetDatabase:
|
|
|
302
324
|
Dataframe containing imbalance prices
|
|
303
325
|
|
|
304
326
|
Raises:
|
|
305
|
-
ValueError: Raises an error
|
|
306
|
-
|
|
307
|
-
ValueError: Raises an error
|
|
327
|
+
ValueError: Raises an error if input arguments 'columns' and 'process_data' are not
|
|
328
|
+
compatible
|
|
329
|
+
ValueError: Raises an error if the combination of trading dates and delivery dates
|
|
308
330
|
is not valid.
|
|
331
|
+
ValueError: Raises an error if match with input commodity name is not unique
|
|
332
|
+
ValueError: Raises an error if input commodity is not supported
|
|
333
|
+
ValueError: Raises an error if no price data is found for user inputs
|
|
309
334
|
"""
|
|
310
335
|
# Input validation
|
|
311
336
|
if process_data and columns is not None:
|
|
@@ -349,6 +374,26 @@ class DetDatabase:
|
|
|
349
374
|
else:
|
|
350
375
|
columns_str = f"[{'], ['.join(columns)}]"
|
|
351
376
|
|
|
377
|
+
# Get commodity information (map code and local timezone)
|
|
378
|
+
# Note: The local timezone is important because ENTSOE provides all prices in the UTC
|
|
379
|
+
# timezone. We first convert the dates from UTC to the local timezone, and then filter
|
|
380
|
+
# for the requested delivery period.
|
|
381
|
+
commodity_info = self.load_commodities(
|
|
382
|
+
columns=["Timezone", "EntsoeMapCode"], conditions=f"WHERE Name='{commodity_name}'"
|
|
383
|
+
)
|
|
384
|
+
if commodity_info.shape[0] > 1:
|
|
385
|
+
raise ValueError(f"More than one match found with commodity '{commodity_name}'.")
|
|
386
|
+
elif commodity_info.shape[0] == 0:
|
|
387
|
+
supported_commodities = self.load_commodities(columns=["Name"])
|
|
388
|
+
supported_commodities_str = ", ".join(f"'{x}'" for x in supported_commodities["Name"])
|
|
389
|
+
raise ValueError(
|
|
390
|
+
f"Commodity '{commodity_name}' is not supported. Supported commodities: "
|
|
391
|
+
f"{supported_commodities_str}."
|
|
392
|
+
)
|
|
393
|
+
else:
|
|
394
|
+
map_code = commodity_info.loc[0, "EntsoeMapCode"]
|
|
395
|
+
timezone = commodity_info.loc[0, "Timezone"]
|
|
396
|
+
|
|
352
397
|
# Convert start trading date to start delivery date
|
|
353
398
|
if start_trading_date is not None:
|
|
354
399
|
start_delivery_date = pd.Timestamp(start_trading_date).floor("D")
|
|
@@ -382,6 +427,9 @@ class DetDatabase:
|
|
|
382
427
|
df = self.query_db(query)
|
|
383
428
|
self.close_connection()
|
|
384
429
|
|
|
430
|
+
if df.empty:
|
|
431
|
+
raise ValueError("No price data found for user-defined inputs.")
|
|
432
|
+
|
|
385
433
|
# Sort data by delivery date
|
|
386
434
|
df.sort_values(
|
|
387
435
|
by=["DateTime(UTC)"], axis=0, ascending=True, inplace=True, ignore_index=True
|
|
@@ -395,40 +443,30 @@ class DetDatabase:
|
|
|
395
443
|
|
|
396
444
|
# Process raw data and convert it to standardized format
|
|
397
445
|
if process_data:
|
|
398
|
-
df = DetDatabase.process_imbalance_prices(df, timezone)
|
|
446
|
+
df = DetDatabase.process_imbalance_prices(df, commodity_name, timezone)
|
|
399
447
|
|
|
400
448
|
return df
|
|
401
449
|
|
|
402
450
|
@staticmethod
|
|
403
|
-
def process_imbalance_prices(
|
|
451
|
+
def process_imbalance_prices(
|
|
452
|
+
df_in: pd.DataFrame, commodity_name: str, timezone: str
|
|
453
|
+
) -> pd.DataFrame:
|
|
404
454
|
"""
|
|
405
455
|
Processes imbalance prices and converts from ENTSOE format to standardized format.
|
|
406
456
|
|
|
407
457
|
Args:
|
|
408
458
|
df_in: Dataframe containing imbalance prices
|
|
459
|
+
commodity_name: Commodity name (as defined in the [META].[Commodity] database table)
|
|
409
460
|
timezone: Timezone of the power country/region
|
|
410
461
|
|
|
411
462
|
Returns:
|
|
412
463
|
Processed dataframe containing imbalance prices
|
|
413
464
|
"""
|
|
414
|
-
map_code_to_commodity_mapper = dict(
|
|
415
|
-
NL={"commodity_name": "DutchPower", "product_code": "Q0B"}
|
|
416
|
-
)
|
|
417
|
-
|
|
418
465
|
# Initialize output dataframe
|
|
419
466
|
df_out = pd.DataFrame()
|
|
420
467
|
|
|
421
468
|
# Set commodity name
|
|
422
|
-
|
|
423
|
-
map_code_to_commodity_mapper[mc]["commodity_name"] for mc in df_in["MapCode"]
|
|
424
|
-
]
|
|
425
|
-
df_out["CommodityName"] = commodity_name
|
|
426
|
-
|
|
427
|
-
# Set product code
|
|
428
|
-
product_code = [
|
|
429
|
-
map_code_to_commodity_mapper[mc]["product_code"] for mc in df_in["MapCode"]
|
|
430
|
-
]
|
|
431
|
-
df_out["ProductCode"] = product_code
|
|
469
|
+
df_out["CommodityName"] = [commodity_name] * df_in.shape[0]
|
|
432
470
|
|
|
433
471
|
# Set trading date
|
|
434
472
|
df_out["TradingDate"] = df_in[f"DateTime({timezone})"].dt.floor("D").values
|
|
@@ -463,16 +501,19 @@ class DetDatabase:
|
|
|
463
501
|
of trading dates.
|
|
464
502
|
|
|
465
503
|
Args:
|
|
466
|
-
commodity_name: Commodity name
|
|
504
|
+
commodity_name: Commodity name (as defined in the [META].[Commodity] database table)
|
|
467
505
|
start_trading_date: Start trading date
|
|
468
506
|
end_trading_date: End trading date
|
|
469
507
|
tenors: Product tenors (e.g. "Month", "Quarter", "Year")
|
|
470
|
-
delivery_type: Delivery type
|
|
508
|
+
delivery_type: Delivery type ("Base", "Peak", "Offpeak")
|
|
471
509
|
columns: Requested database table columns. Set columns=["*"] (i.e. as list) to get
|
|
472
510
|
all columns.
|
|
473
511
|
|
|
474
512
|
Returns:
|
|
475
513
|
Dataframe containing futures end-of-day settlement prices
|
|
514
|
+
|
|
515
|
+
Raises:
|
|
516
|
+
ValueError: Raises an error if no price data is found for user inputs
|
|
476
517
|
"""
|
|
477
518
|
# Set default column values
|
|
478
519
|
if columns is None:
|
|
@@ -507,6 +548,9 @@ class DetDatabase:
|
|
|
507
548
|
df = self.query_db(query)
|
|
508
549
|
self.close_connection()
|
|
509
550
|
|
|
551
|
+
if df.empty:
|
|
552
|
+
raise ValueError("No price data found for user-defined inputs.")
|
|
553
|
+
|
|
510
554
|
# Sort data
|
|
511
555
|
df.sort_values(
|
|
512
556
|
by=["TradingDate", "DeliveryStart", "DeliveryEnd"],
|
|
@@ -523,12 +567,84 @@ class DetDatabase:
|
|
|
523
567
|
|
|
524
568
|
return df
|
|
525
569
|
|
|
570
|
+
def load_commodities(self, columns: list = None, conditions: str = None) -> pd.DataFrame:
|
|
571
|
+
"""
|
|
572
|
+
General method to load data from the database's commodity table.
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
columns: Requested database table columns. Set columns=["*"] (i.e. as list) to get
|
|
576
|
+
all columns.
|
|
577
|
+
conditions: Optional conditions to add to SQL query. E.g. "WHERE Name='DutchPower'".
|
|
578
|
+
|
|
579
|
+
Returns:
|
|
580
|
+
Table data
|
|
581
|
+
"""
|
|
582
|
+
# Set default column values
|
|
583
|
+
if columns is None:
|
|
584
|
+
columns = ["*"]
|
|
585
|
+
|
|
586
|
+
# Convert columns from list to string
|
|
587
|
+
if len(columns) == 1:
|
|
588
|
+
columns_str = str(columns[0])
|
|
589
|
+
else:
|
|
590
|
+
columns_str = f"[{'], ['.join(columns)}]"
|
|
591
|
+
|
|
592
|
+
# Create query
|
|
593
|
+
table = DetDatabaseDefinitions.DEFINITIONS["table_name_commodity"]
|
|
594
|
+
query = f"SELECT {columns_str} FROM {table} {conditions}"
|
|
595
|
+
|
|
596
|
+
# Query db
|
|
597
|
+
self.open_connection()
|
|
598
|
+
df = self.query_db(query)
|
|
599
|
+
self.close_connection()
|
|
600
|
+
|
|
601
|
+
return df
|
|
602
|
+
|
|
603
|
+
def get_commodity_info(
|
|
604
|
+
self, filter_column: str, filter_value: str, info_columns: list
|
|
605
|
+
) -> dict:
|
|
606
|
+
"""
|
|
607
|
+
Finds information related to a specific, user-defined commodity.
|
|
608
|
+
|
|
609
|
+
Args:
|
|
610
|
+
filter_column: Column used to filter data for one specific commodity
|
|
611
|
+
filter_value: Value used to filter data for one specific commodity
|
|
612
|
+
info_columns: Columns containing the requested information
|
|
613
|
+
|
|
614
|
+
Returns:
|
|
615
|
+
A dictionary containing the requested information
|
|
616
|
+
|
|
617
|
+
Raises:
|
|
618
|
+
ValueError: Raises an error if match with input filter value is not unique
|
|
619
|
+
ValueError: Raises an error if the input filter value is not found
|
|
620
|
+
"""
|
|
621
|
+
# Get commodity information for user-defined filtering criteria
|
|
622
|
+
condition = f"WHERE {filter_column}='{filter_value}'"
|
|
623
|
+
commodity_info = self.load_commodities(columns=info_columns, conditions=condition)
|
|
624
|
+
|
|
625
|
+
# Validate response
|
|
626
|
+
if commodity_info.shape[0] > 1:
|
|
627
|
+
raise ValueError(f"More than one match found for {filter_column}={filter_value}.")
|
|
628
|
+
|
|
629
|
+
elif commodity_info.shape[0] == 0:
|
|
630
|
+
available_values = self.load_commodities(columns=[filter_column])
|
|
631
|
+
available_values_str = ", ".join(f"'{x}'" for x in available_values[filter_column])
|
|
632
|
+
raise ValueError(
|
|
633
|
+
f"Value {filter_value} not found in column '{filter_column}'. Available values: "
|
|
634
|
+
f"{available_values_str}."
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
# Convert dataframe row to dict
|
|
638
|
+
commodity_info = commodity_info.loc[0, :].to_dict()
|
|
639
|
+
|
|
640
|
+
return commodity_info
|
|
641
|
+
|
|
526
642
|
|
|
527
643
|
class DetDatabaseDefinitions:
|
|
528
644
|
"""A class containing some hard-coded definitions related to the DET database."""
|
|
529
645
|
|
|
530
646
|
DEFINITIONS = dict(
|
|
531
|
-
|
|
647
|
+
table_name_commodity="[META].[Commodity]",
|
|
532
648
|
table_name_entsoe_day_ahead_spot_price="[ENTSOE].[DayAheadSpotPrice]",
|
|
533
649
|
table_name_entsoe_imbalance_price="[ENTSOE].[ImbalancePrice]",
|
|
534
650
|
table_name_futures_eod_settlement_price="[VW].[EODSettlementPrice]",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|