51
51
# ## Getting Data
52
52
# define price error dir
53
53
data_dir = Path ("price-error" )
54
+ nemosis_cache = Path ("nemosis_cache/" )
54
55
55
56
# %% [markdown]
56
57
# ### Obtaining actual price data from `NEMOSIS`
57
58
# We will download `DISPATCHPRICE` to access the `RRP` (energy price) field and cache it so that it's ready for computation.
58
59
59
60
# %%
60
61
if not data_dir .exists ():
61
- nemosis_cache = Path ("nemosis_cache/" )
62
62
if not nemosis_cache .exists ():
63
63
nemosis_cache .mkdir (parents = True )
64
64
nemosis .cache_compiler (
@@ -251,6 +251,7 @@ def process_price_error(
251
251
fname = f"price-error-{ start .year } .parquet"
252
252
if Path (data_dir , fname ).exists ():
253
253
print (f"Price error { analysis_start_dt .year + i } file exists, continuing" )
254
+ continue
254
255
else :
255
256
end = datetime (
256
257
start .year + 1 ,
@@ -260,11 +261,12 @@ def process_price_error(
260
261
start .minute ,
261
262
start .second ,
262
263
)
263
- print (f"Calculating price errors for year { start .year } " )
264
- price_error = calculate_price_error (
265
- start .strftime (dt_str_format ), end .strftime (dt_str_format )
266
- )
267
- price_error .to_parquet (Path (data_dir , fname ))
264
+
265
+ print (f"Calculating price errors for year { start .year } " )
266
+ price_error = calculate_price_error (
267
+ start .strftime (dt_str_format ), end .strftime (dt_str_format )
268
+ )
269
+ price_error .to_parquet (Path (data_dir , fname ))
268
270
269
271
# %% [markdown]
270
272
# ## Price Error Count by Severity and Year
@@ -299,7 +301,7 @@ def plot_counts_within_horizon(
299
301
i = 0
300
302
price_errors_lazy = pl .scan_parquet (price_errors_dir / Path ("*.parquet" ))
301
303
price_errors_lazy = price_errors_lazy .filter (
302
- pl .col ("ahead_time" ) < pl .duration (minutes = horizon_minutes )
304
+ pl .col ("ahead_time" ) <= pl .duration (minutes = horizon_minutes )
303
305
)
304
306
price_errors_df = price_errors_lazy .collect ().to_pandas ()
305
307
price_errors_df .set_index ("forecasted_time" , inplace = True )
@@ -379,16 +381,18 @@ def annotate_ax(
379
381
380
382
381
383
fig , axes = plt .subplots (
382
- 2 , 1 , sharex = True , sharey = True ,
384
+ 3 , 1 , sharex = True ,
383
385
)
384
- for horizon , ax in zip ((24 * 60 , 1 * 60 ), axes .flatten ()):
386
+ for horizon , ax in zip ((24 * 60 , 2 * 60 , 15 ), axes .flatten ()):
385
387
plot_counts_within_horizon (ax , data_dir , horizon )
386
388
387
389
annotate_ax (axes [0 ], annotate = True , vline_ymax = 1.1 , y_annot = 29e3 , annot_fontsize = 6 )
388
390
annotate_ax (axes [1 ], annotate = False , vline_ymax = 1.1 , y_annot = 29e3 , annot_fontsize = 6 )
391
+ annotate_ax (axes [2 ], annotate = False , vline_ymax = 1.1 , y_annot = 29e3 , annot_fontsize = 6 )
389
392
fig .suptitle ("NEM-wide Monthly Count of Price Forecast Errors" , fontsize = 16 )
390
- axes [0 ].set_title ("Within day-ahead horizon (30MPD & 5MPD)" , loc = "left" , fontsize = 10 )
391
- axes [1 ].set_title ("Within hour-ahead horizon (5MPD)" , loc = "left" , fontsize = 10 )
393
+ axes [0 ].set_title ("Up to a day ahead (30MPD & 5MPD)" , loc = "left" , fontsize = 10 )
394
+ axes [1 ].set_title ("Up to two hours ahead (30MPD & 5MPD)" , loc = "left" , fontsize = 10 )
395
+ axes [2 ].set_title ("Up to 15 minutes ahead (5MPD)" , loc = "left" , fontsize = 10 )
392
396
for ax in axes .flatten ():
393
397
ax .set_ylabel ("Count" , fontsize = 7 )
394
398
handles , labels = axes [0 ].get_legend_handles_labels ()
0 commit comments