|
import requests |
|
from datetime import datetime, date, timedelta |
|
import pandas as pd |
|
from features import calendar |
|
|
|
def electricity_prices(historical: bool = False, area: list = None, start: str = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d"), end: str = (date.today()).strftime("%Y-%m-%d")) -> pd.DataFrame: |
|
""" |
|
Fetches electricity prices from Energinet (Dataservice API). |
|
|
|
Parameters: |
|
- historical (bool): If True, fetches historical data from start date to end date. If False, fetches data for the current day. Default is False. |
|
- area (list): Define the area for the API call. Default is None. |
|
- start (str): Define a start date for the API call. Default is 'Yesterday'. |
|
- end (str): Define a end date for the API call. Default is 'Today'. |
|
|
|
Returns: |
|
- pd.DataFrame: DataFrame with electricity prices for different areas in Denmark (DK1, DK2). |
|
""" |
|
|
|
|
|
API_URL = 'https://api.energidataservice.dk/dataset/Elspotprices' |
|
r = requests.get(API_URL , params={ |
|
'offset': 0, |
|
'start': start+'T00:00', |
|
'end': end+'T23:59', |
|
'filter': '{"PriceArea":["DK1", "DK2"]}', |
|
'sort': 'HourUTC DESC' |
|
}) |
|
|
|
|
|
data = r.json()['records'] |
|
df = pd.DataFrame(data) |
|
|
|
|
|
df["date"] = df["HourDK"].map(lambda x: datetime.strptime(x, '%Y-%m-%dT%H:%M:%S').strftime("%Y-%m-%d")) |
|
df['datetime'] = pd.to_datetime(df['HourDK']) |
|
df['hour'] = pd.to_datetime(df['datetime']).dt.hour |
|
df['date'] = pd.to_datetime(df['date']) |
|
|
|
|
|
df['SpotPriceDKK_KWH'] = df['SpotPriceDKK'] / 1000 |
|
|
|
|
|
df.drop('SpotPriceDKK', axis=1, inplace=True) |
|
|
|
|
|
if area is None: |
|
filtered_df = df |
|
else: |
|
filtered_df = df[df['PriceArea'].isin(area)] |
|
|
|
|
|
today = (date.today()).strftime("%Y-%m-%d") |
|
if historical: |
|
filtered_df = filtered_df[filtered_df.date != today] |
|
else: |
|
filtered_df = filtered_df[filtered_df.date == today] |
|
|
|
|
|
filtered_df["timestamp"] = filtered_df["datetime"].apply(lambda x: int(x.timestamp() * 1000)) |
|
|
|
|
|
filtered_df.reset_index(drop=True, inplace=True) |
|
|
|
|
|
reordered_df = filtered_df[['timestamp', 'datetime', 'date', 'hour', 'PriceArea', 'SpotPriceDKK_KWH']] |
|
|
|
|
|
reordered_df = reordered_df.melt(id_vars=['timestamp', 'datetime', 'date', 'hour', "PriceArea"], var_name="attribute", value_name="value") |
|
|
|
|
|
reordered_df["heading"] = reordered_df["PriceArea"] + "_" + reordered_df["attribute"] |
|
|
|
|
|
reordered_df.drop(columns=["PriceArea"], inplace=True) |
|
reordered_df.drop(columns=["attribute"], inplace=True) |
|
|
|
|
|
electricity_prices = reordered_df.pivot_table(index=['timestamp', 'datetime', 'date', 'hour'], columns="heading", values="value").reset_index() |
|
|
|
|
|
electricity_prices.columns = list(map(str.lower, electricity_prices.columns)) |
|
|
|
|
|
electricity_prices.columns = electricity_prices.columns.str.replace(' ', '_') |
|
|
|
|
|
return electricity_prices |
|
|
|
def electricity_prices_window(historical: bool = False, area: list = None, start: str = ('2020-01-01'), end: str = datetime.now().date() + timedelta(days=(7*1))) -> pd.DataFrame: |
|
""" |
|
Fetches electricity prices and make rolling windows. |
|
|
|
Parameters: |
|
- historical (bool): If True, fetches historical data from start date to end date. If False, fetches data for the current day. Default is False. |
|
- area (list): List of areas to fetch data for. Default is None. |
|
- start (str): Define a start date for the API call. Default is '2020-01-01'. |
|
- end (str): Define a end date for the API call. Default is one week from today. |
|
|
|
Returns: |
|
- pd.DataFrame: DataFrame with electricity prices window. |
|
""" |
|
|
|
electricity_df = electricity_prices( |
|
historical=True, |
|
area=area, |
|
start=start |
|
) |
|
|
|
calendar_hours_df = calendar.calendar_denmark( |
|
freq='H', |
|
start=start, |
|
end=end |
|
) |
|
|
|
|
|
merge_data = pd.merge(electricity_df, calendar_hours_df, how='right', left_on='timestamp', right_on='timestamp') |
|
|
|
|
|
merge_data = merge_data.drop(columns=['date_x', 'datetime_x', 'hour_x']) |
|
merge_data = merge_data.rename(columns={'date_y': 'date', |
|
'datetime_y': 'datetime', |
|
'hour_y': 'hour'}) |
|
|
|
merge_data_for_rolling = merge_data |
|
|
|
|
|
today = datetime.today().date() |
|
|
|
|
|
mask = merge_data_for_rolling['datetime'].dt.date < today |
|
|
|
|
|
|
|
merge_data_for_rolling.loc[mask, 'dk1_spotpricedkk_kwh'] = merge_data_for_rolling['dk1_spotpricedkk_kwh'].ffill() |
|
|
|
|
|
electricity_window_df = merge_data_for_rolling |
|
|
|
|
|
electricity_window_df['prev_1w_mean'] = electricity_window_df['dk1_spotpricedkk_kwh'].rolling(window=24*(1*7), min_periods=1).mean() |
|
|
|
|
|
electricity_window_df['prev_2w_mean'] = electricity_window_df['dk1_spotpricedkk_kwh'].rolling(window=24*(2*7), min_periods=1).mean() |
|
|
|
|
|
electricity_window_df['prev_4w_mean'] = electricity_window_df['dk1_spotpricedkk_kwh'].rolling(window=24*(4*7), min_periods=1).mean() |
|
|
|
|
|
electricity_window_df['prev_6w_mean'] = electricity_window_df['dk1_spotpricedkk_kwh'].rolling(window=24*(6*7), min_periods=1).mean() |
|
|
|
|
|
electricity_window_df['prev_8w_mean'] = electricity_window_df['dk1_spotpricedkk_kwh'].rolling(window=24*(8*7), min_periods=1).mean() |
|
|
|
|
|
electricity_window_df['prev_12w_mean'] = electricity_window_df['dk1_spotpricedkk_kwh'].rolling(window=24*(12*7), min_periods=1).mean() |
|
|
|
|
|
today = (date.today()).strftime("%Y-%m-%d") |
|
if historical: |
|
electricity_window_df_filtered = electricity_window_df[electricity_window_df.date < today] |
|
else: |
|
electricity_window_df_filtered = electricity_window_df[electricity_window_df.date >= today] |
|
|
|
|
|
electricity_window_df_filtered=electricity_window_df_filtered[['timestamp', 'datetime', 'prev_1w_mean', 'prev_2w_mean', 'prev_4w_mean', 'prev_6w_mean', 'prev_8w_mean', 'prev_12w_mean']] |
|
|
|
|
|
return electricity_window_df_filtered |