@@ -241,16 +241,19 @@ def fetch(self, start: pd.Timestamp, end: pd.Timestamp) -> pd.DataFrame:
241241 chunk_data = self ._fetch_chunk (chunk_start , chunk_end )
242242
243243 for dtype in self .type :
244- if dtype in chunk_data :
245- all_results [dtype ].append (chunk_data [dtype ])
244+ chunk_df = chunk_data .get (dtype )
245+ if chunk_df is not None and not chunk_df .empty :
246+ all_results [dtype ].append (chunk_df )
246247 progress .advance (task )
247248
248249 dataframes = []
249250 for dtype in self .type :
250251 if all_results [dtype ]:
251252 df = pd .concat (all_results [dtype ]).sort_index ()
252- df = df [~ df .index .duplicated (keep = "first" )]
253- dataframes .append (df )
253+ if df .index .has_duplicates :
254+ df = df .groupby (level = 0 ).first ()
255+ if not df .empty :
256+ dataframes .append (df )
254257
255258 elapsed = time .time () - start_time
256259 self ._log_success (elapsed )
@@ -301,7 +304,9 @@ def _fetch_load(self, start: pd.Timestamp, end: pd.Timestamp) -> pd.DataFrame:
301304 start ,
302305 end ,
303306 )
304- dfs .append (self ._parse_loads (xml , "A16" ))
307+ df_actual = self ._parse_loads (xml , "A16" )
308+ if not df_actual .empty :
309+ dfs .append (df_actual )
305310
306311 xml = self ._api_request (
307312 {
@@ -312,7 +317,9 @@ def _fetch_load(self, start: pd.Timestamp, end: pd.Timestamp) -> pd.DataFrame:
312317 start ,
313318 end ,
314319 )
315- dfs .append (self ._parse_loads (xml , "A01" ))
320+ df_forecast = self ._parse_loads (xml , "A01" )
321+ if not df_forecast .empty :
322+ dfs .append (df_forecast )
316323
317324 xml = self ._api_request (
318325 {
@@ -323,10 +330,17 @@ def _fetch_load(self, start: pd.Timestamp, end: pd.Timestamp) -> pd.DataFrame:
323330 start ,
324331 end ,
325332 )
326- dfs .append (self ._parse_loads (xml , "A31" ))
333+ df_week = self ._parse_loads (xml , "A31" )
334+ if not df_week .empty :
335+ dfs .append (df_week )
336+ elif xml is not None :
337+ self .logger .warning (f"ENTSOE [{ self ._area_name } ]: A31 (week-ahead forecast) data available but no min/max values found" )
338+
339+ if not dfs :
340+ return pd .DataFrame ()
327341
328342 result = pd .concat (dfs , axis = 1 )
329- return result .truncate (before = start , after = end )
343+ return result .truncate (before = start - pd . Timedelta ( days = 1 ) , after = end )
330344
331345 def _fetch_generation (self , start : pd .Timestamp , end : pd .Timestamp ) -> pd .DataFrame :
332346 dfs = []
@@ -342,17 +356,6 @@ def _fetch_generation(self, start: pd.Timestamp, end: pd.Timestamp) -> pd.DataFr
342356 )
343357 dfs .append (self ._parse_generation (xml ).add_prefix ("generation_" ))
344358
345- xml = self ._api_request (
346- {
347- "documentType" : "A69" ,
348- "processType" : "A01" ,
349- "in_Domain" : self ._area_code ,
350- },
351- start ,
352- end ,
353- )
354- dfs .append (self ._parse_generation (xml ).add_prefix ("generation_" ))
355-
356359 xml = self ._api_request (
357360 {
358361 "documentType" : "A69" ,
@@ -381,10 +384,12 @@ def _fetch_price(self, start: pd.Timestamp, end: pd.Timestamp) -> pd.DataFrame:
381384 price_dict = self ._parse_prices (xml )
382385
383386 series = pd .Series ()
384- if price_dict ["60min" ] is not None and len (price_dict ["60min" ]) > 0 :
385- series = price_dict ["60min" ]
386- elif price_dict ["15min" ] is not None and len (price_dict ["15min" ]) > 0 :
387+ if price_dict ["15min" ] is not None and len (price_dict ["15min" ]) > 0 :
387388 series = price_dict ["15min" ]
389+ elif price_dict ["30min" ] is not None and len (price_dict ["30min" ]) > 0 :
390+ series = price_dict ["30min" ]
391+ elif price_dict ["60min" ] is not None and len (price_dict ["60min" ]) > 0 :
392+ series = price_dict ["60min" ]
388393
389394 series = series .truncate (before = start , after = end )
390395
@@ -433,15 +438,15 @@ def _parse_loads(self, xml_text: str, process_type: str) -> pd.DataFrame:
433438 elif bsn_type and bsn_type .text == "A61" :
434439 series_max_list .append (t )
435440
436- series_min = pd .concat (series_min_list ) if series_min_list else pd .Series (dtype = float )
437- series_max = pd .concat (series_max_list ) if series_max_list else pd .Series (dtype = float )
441+ result_dict = {}
442+ if series_min_list :
443+ series_min = pd .concat (series_min_list ).sort_index ()
444+ result_dict ["load_forecast_daily_min" ] = series_min
445+ if series_max_list :
446+ series_max = pd .concat (series_max_list ).sort_index ()
447+ result_dict ["load_forecast_daily_max" ] = series_max
438448
439- return pd .DataFrame (
440- {
441- "load_forecast_daily_min" : series_min ,
442- "load_forecast_daily_max" : series_max ,
443- }
444- )
449+ return pd .DataFrame (result_dict ) if result_dict else pd .DataFrame ()
445450
446451 def _parse_generation (self , xml_text : str ) -> pd .DataFrame :
447452 if xml_text is None :
0 commit comments