File size: 5,953 Bytes
ae2aee0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97b331e
ae2aee0
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import gradio as gr
import pandas as pd
import numpy as np
import hopsworks
import joblib
import os
import json
from entsoe import EntsoePandasClient
from datetime import datetime, timedelta, date
from pandas import json_normalize
import tensorflow as tf
from keras.layers import LSTM
from urllib.request import urlopen
from sklearn.preprocessing import LabelEncoder, StandardScaler


# from keras.layers import *
# from keras.models import Sequential
# from keras.layers import Dense
# from keras.layers import LSTM
# from keras.layers import Dropout

project = hopsworks.login()
fs = project.get_feature_store()

mr = project.get_model_registry()
model = mr.get_model("SE3_elec_price_model", version=2)
model_dir = model.download()
model = joblib.load(model_dir + "/electricity_price.pkl")

def get_price_forecast():
    today, tomorrow = get_date()

    df_entsoe = get_entsoe_data(today, tomorrow)

    # get timestamps that temp dataset should match on
    entsoe_earliest = df_entsoe["datetime"].iloc[0]
    entsoe_latest = df_entsoe["datetime"].iloc[-1]
    df_temp = get_temp(entsoe_earliest, entsoe_latest)
    
    df = df_entsoe.merge(df_temp, how='inner', on='datetime')
    df.set_index('datetime',inplace=True)

    ## pre-process before predict
    sc_x=StandardScaler()
    df_scaled=sc_x.fit_transform(df)
    sc_y=StandardScaler()
    sc_y=sc_y.fit(df[['day_ahead_price']])

    step_back=24
    no_records=len(df_scaled)
    no_cols=4
    X_train_shape_pred=[]
    for i in range(step_back,no_records):
        X_train_shape_pred.append(df_scaled[i-step_back:i])
    X_train_shape_pred=np.array(X_train_shape_pred)
    print(X_train_shape_pred.shape)

    ## predict
    pred_price = model.predict(X_train_shape_pred)
    final_pred=sc_y.inverse_transform(pred_price)
    print(final_pred.shape)

    # append time for prediction
    predict_time_from = datetime.fromtimestamp(entsoe_latest / 1e3)
    # calculating timestamps for the next 24 h
    timestamp_list = [predict_time_from + timedelta(hours=x) for x in range(len(final_pred))]
    
    # iterating through timestamp_list
    # for i, x in enumerate(timestamp_list):
    #     print(x, final_pred[i])
    # print(final_pred.shape)
    df_prediction = pd.DataFrame(
        {'Datetime': timestamp_list,
        'Price forecast [EUR/MWh]': final_pred.flatten(),
        })
    
    #df_predictions = pd.DataFrame([timestamp_list, final_pred], columns=["datetime", "Price prediction"])
    # print(len(final_pred), len(timestamp_list), len(final_pred), len(final_pred[0]))

    return df_prediction
    #[today, temp, day_ahead_price, pred_price, total_load, total_generation]

# # Returns yesterday and tomorrows date
def get_date():
    # yesterday = datetime.today() - timedelta(days=1)
    # yesterday = yesterday.date().strftime('%Y%m%d')
    # tomorrow = (datetime.strptime(yesterday, '%Y%m%d') + timedelta(days=2)).strftime('%Y%m%d')

    date_from = datetime.now() - timedelta(days=3)
    date_from = date_from.date().strftime('%Y%m%d')
    date_to = (datetime.strptime(date_from, '%Y%m%d') + timedelta(days=4)).strftime('%Y%m%d')

    return date_from, date_to

def get_entsoe_data(date_from, date_to):
    # Client
    client = EntsoePandasClient(api_key="cb3a29b2-3276-4a4c-aba3-6507120d99be")

    # Date and country
    start = pd.Timestamp(date_from, tz='Europe/Stockholm')
    end = pd.Timestamp(date_to, tz='Europe/Stockholm')
    country_code = 'SE_3'  

    df_day_price = client.query_day_ahead_prices(country_code, start=start,end=end)
    df_generation_per_prod = client.query_generation(country_code, start=start,end=end, psr_type=None)    
    df_load = client.query_load(country_code, start=start,end=end)

    df_entsoe = df_generation_per_prod.join(df_day_price.rename("day_ahead_price"))
    df_entsoe = df_entsoe.join(df_load)

    df_entsoe_clean = df_entsoe.reset_index()
    df_entsoe_clean = df_entsoe_clean.rename(columns = {'index':'DateTime'})
    df_entsoe_clean['DateTime'] = df_entsoe_clean.DateTime.values.astype('int64') // 10 ** 6

    col_list = ["Hydro Water Reservoir", "Nuclear", "Other", "Solar", "Wind Onshore"]
    df_entsoe_clean['total_generation'] = df_entsoe_clean[list(col_list)].sum(axis=1)

    df_entsoe_clean.drop(col_list + ["Fossil Gas"], axis=1, inplace=True)
    df_entsoe_clean.rename(columns={"Actual Load": "total_load", "DateTime":"datetime"}, inplace=True)

    return df_entsoe_clean.tail(48)

def get_temp(timeseries_from, timeseries_to):

    url = "https://opendata-download-metobs.smhi.se/api/version/latest/parameter/1/station/71420/period/latest-months/data.json"
    response = urlopen(url)

    # convert response to json, to dataframe
    data_json = json.loads(response.read())
    df_smhi_data = json_normalize(data_json['value']) 

    # extract only the temperature in the time stamp interval
    df_smhi_data = df_smhi_data.loc[(df_smhi_data['date'] >= timeseries_from) & (df_smhi_data['date'] <= timeseries_to)]
    df_smhi_data = df_smhi_data.reset_index().rename(columns = {'date':'datetime'})

    df_smhi_data.drop(["index", "quality"], axis=1, inplace=True)
    df_smhi_data["value"] = df_smhi_data["value"].astype(float)
    df_smhi_data.rename(columns={"value": "temperature"}, inplace=True)

    return df_smhi_data

demo = gr.Interface(
    fn = get_price_forecast,
    title = "SE3 Electricity Day-Ahead Price Prediction",
    description ="SE3 Electricity Day-Ahead Price Prediction, based on electricity production, generation and temperature",
    allow_flagging = "never",
    inputs = [],
    outputs = [
        gr.DataFrame(x="datetime", y="Price prediction [EUR/MWh]")
        # gr.Textbox(label="Date"),
        # gr.Textbox(label="Temperature Forecast [℃]"),
        # gr.Textbox(label="Total Load Forecast [MWh]"),
        # gr.Textbox(label="Total Generation Forecast [MWh]"),
        # gr.Textbox(label="Predicted Day-Ahead Price [EUR/MWh]"),   
    ]
)

demo.launch()