Spaces:
Runtime error
Runtime error
AbyelT commited on
Commit ·
ae2aee0
1
Parent(s): 9daba69
price prediction v1
Browse files- .hw_api_key +1 -0
- app.py +167 -0
- requirements.txt +7 -0
.hw_api_key
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
e76DLTFJzKMcADkC.BEKfBjsL91EXI2qgX9PPOcryLnsqaXWlME4EBWIPrMH8wLLUpdcmN6H3uqZuSO7J
|
app.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import hopsworks
|
| 5 |
+
import joblib
|
| 6 |
+
import os
|
| 7 |
+
import json
|
| 8 |
+
from entsoe import EntsoePandasClient
|
| 9 |
+
from datetime import datetime, timedelta, date
|
| 10 |
+
from pandas import json_normalize
|
| 11 |
+
import tensorflow as tf
|
| 12 |
+
from keras.layers import LSTM
|
| 13 |
+
from urllib.request import urlopen
|
| 14 |
+
from sklearn.preprocessing import LabelEncoder, StandardScaler
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
# from keras.layers import *
|
| 18 |
+
# from keras.models import Sequential
|
| 19 |
+
# from keras.layers import Dense
|
| 20 |
+
# from keras.layers import LSTM
|
| 21 |
+
# from keras.layers import Dropout
|
| 22 |
+
|
| 23 |
+
project = hopsworks.login()
|
| 24 |
+
fs = project.get_feature_store()
|
| 25 |
+
|
| 26 |
+
mr = project.get_model_registry()
|
| 27 |
+
model = mr.get_model("SE3_elec_price_model", version=2)
|
| 28 |
+
model_dir = model.download()
|
| 29 |
+
model = joblib.load(model_dir + "/electricity_price.pkl")
|
| 30 |
+
|
| 31 |
+
def get_price_forecast():
|
| 32 |
+
today, tomorrow = get_date()
|
| 33 |
+
|
| 34 |
+
df_entsoe = get_entsoe_data(today, tomorrow)
|
| 35 |
+
|
| 36 |
+
# get timestamps that temp dataset should match on
|
| 37 |
+
entsoe_earliest = df_entsoe["datetime"].iloc[0]
|
| 38 |
+
entsoe_latest = df_entsoe["datetime"].iloc[-1]
|
| 39 |
+
df_temp = get_temp(entsoe_earliest, entsoe_latest)
|
| 40 |
+
|
| 41 |
+
df = df_entsoe.merge(df_temp, how='inner', on='datetime')
|
| 42 |
+
df.set_index('datetime',inplace=True)
|
| 43 |
+
|
| 44 |
+
## pre-process before predict
|
| 45 |
+
sc_x=StandardScaler()
|
| 46 |
+
df_scaled=sc_x.fit_transform(df)
|
| 47 |
+
sc_y=StandardScaler()
|
| 48 |
+
sc_y=sc_y.fit(df[['day_ahead_price']])
|
| 49 |
+
|
| 50 |
+
step_back=24
|
| 51 |
+
no_records=len(df_scaled)
|
| 52 |
+
no_cols=4
|
| 53 |
+
X_train_shape_pred=[]
|
| 54 |
+
for i in range(step_back,no_records):
|
| 55 |
+
X_train_shape_pred.append(df_scaled[i-step_back:i])
|
| 56 |
+
X_train_shape_pred=np.array(X_train_shape_pred)
|
| 57 |
+
print(X_train_shape_pred.shape)
|
| 58 |
+
|
| 59 |
+
## predict
|
| 60 |
+
pred_price = model.predict(X_train_shape_pred)
|
| 61 |
+
final_pred=sc_y.inverse_transform(pred_price)
|
| 62 |
+
print(final_pred.shape)
|
| 63 |
+
|
| 64 |
+
# append time for prediction
|
| 65 |
+
predict_time_from = datetime.fromtimestamp(entsoe_latest / 1e3)
|
| 66 |
+
# calculating timestamps for the next 24 h
|
| 67 |
+
timestamp_list = [predict_time_from + timedelta(hours=x) for x in range(len(final_pred))]
|
| 68 |
+
|
| 69 |
+
# iterating through timestamp_list
|
| 70 |
+
# for i, x in enumerate(timestamp_list):
|
| 71 |
+
# print(x, final_pred[i])
|
| 72 |
+
# print(final_pred.shape)
|
| 73 |
+
df_prediction = pd.DataFrame(
|
| 74 |
+
{'Datetime': timestamp_list,
|
| 75 |
+
'Price forecast [EUR/MWh]': final_pred.flatten(),
|
| 76 |
+
})
|
| 77 |
+
|
| 78 |
+
#df_predictions = pd.DataFrame([timestamp_list, final_pred], columns=["datetime", "Price prediction"])
|
| 79 |
+
# print(len(final_pred), len(timestamp_list), len(final_pred), len(final_pred[0]))
|
| 80 |
+
|
| 81 |
+
return df_prediction
|
| 82 |
+
#[today, temp, day_ahead_price, pred_price, total_load, total_generation]
|
| 83 |
+
|
| 84 |
+
# # Returns yesterday and tomorrows date
|
| 85 |
+
def get_date():
|
| 86 |
+
# yesterday = datetime.today() - timedelta(days=1)
|
| 87 |
+
# yesterday = yesterday.date().strftime('%Y%m%d')
|
| 88 |
+
# tomorrow = (datetime.strptime(yesterday, '%Y%m%d') + timedelta(days=2)).strftime('%Y%m%d')
|
| 89 |
+
|
| 90 |
+
date_from = datetime.now() - timedelta(days=3)
|
| 91 |
+
date_from = date_from.date().strftime('%Y%m%d')
|
| 92 |
+
date_to = (datetime.strptime(date_from, '%Y%m%d') + timedelta(days=4)).strftime('%Y%m%d')
|
| 93 |
+
|
| 94 |
+
return date_from, date_to
|
| 95 |
+
|
| 96 |
+
def get_entsoe_data(date_from, date_to):
|
| 97 |
+
# Client
|
| 98 |
+
client = EntsoePandasClient(api_key="cb3a29b2-3276-4a4c-aba3-6507120d99be")
|
| 99 |
+
|
| 100 |
+
# Date and country
|
| 101 |
+
start = pd.Timestamp(date_from, tz='Europe/Stockholm')
|
| 102 |
+
end = pd.Timestamp(date_to, tz='Europe/Stockholm')
|
| 103 |
+
country_code = 'SE_3'
|
| 104 |
+
|
| 105 |
+
df_day_price = client.query_day_ahead_prices(country_code, start=start,end=end)
|
| 106 |
+
df_generation_per_prod = client.query_generation(country_code, start=start,end=end, psr_type=None)
|
| 107 |
+
df_load = client.query_load(country_code, start=start,end=end)
|
| 108 |
+
|
| 109 |
+
df_entsoe = df_generation_per_prod.join(df_day_price.rename("day_ahead_price"))
|
| 110 |
+
df_entsoe = df_entsoe.join(df_load)
|
| 111 |
+
|
| 112 |
+
df_entsoe_clean = df_entsoe.reset_index()
|
| 113 |
+
df_entsoe_clean = df_entsoe_clean.rename(columns = {'index':'DateTime'})
|
| 114 |
+
df_entsoe_clean['DateTime'] = df_entsoe_clean.DateTime.values.astype('int64') // 10 ** 6
|
| 115 |
+
|
| 116 |
+
col_list = ["Hydro Water Reservoir", "Nuclear", "Other", "Solar", "Wind Onshore"]
|
| 117 |
+
df_entsoe_clean['total_generation'] = df_entsoe_clean[list(col_list)].sum(axis=1)
|
| 118 |
+
|
| 119 |
+
df_entsoe_clean.drop(col_list + ["Fossil Gas"], axis=1, inplace=True)
|
| 120 |
+
df_entsoe_clean.rename(columns={"Actual Load": "total_load", "DateTime":"datetime"}, inplace=True)
|
| 121 |
+
|
| 122 |
+
return df_entsoe_clean.tail(48)
|
| 123 |
+
|
| 124 |
+
def get_temp(timeseries_from, timeseries_to):
|
| 125 |
+
|
| 126 |
+
url = "https://opendata-download-metobs.smhi.se/api/version/latest/parameter/1/station/71420/period/latest-months/data.json"
|
| 127 |
+
response = urlopen(url)
|
| 128 |
+
|
| 129 |
+
# convert response to json, to dataframe
|
| 130 |
+
data_json = json.loads(response.read())
|
| 131 |
+
df_smhi_data = json_normalize(data_json['value'])
|
| 132 |
+
|
| 133 |
+
# extract only the temperature in the time stamp interval
|
| 134 |
+
df_smhi_data = df_smhi_data.loc[(df_smhi_data['date'] >= timeseries_from) & (df_smhi_data['date'] <= timeseries_to)]
|
| 135 |
+
df_smhi_data = df_smhi_data.reset_index().rename(columns = {'date':'datetime'})
|
| 136 |
+
|
| 137 |
+
df_smhi_data.drop(["index", "quality"], axis=1, inplace=True)
|
| 138 |
+
df_smhi_data["value"] = df_smhi_data["value"].astype(float)
|
| 139 |
+
df_smhi_data.rename(columns={"value": "temperature"}, inplace=True)
|
| 140 |
+
|
| 141 |
+
return df_smhi_data
|
| 142 |
+
|
| 143 |
+
demo = gr.Interface(
|
| 144 |
+
fn = get_price_forecast,
|
| 145 |
+
title = "SE3 Electricity Day-Ahead Price Prediction",
|
| 146 |
+
description ="SE3 Electricity Day-Ahead Price Prediction, based on electricity production, generation and temperature",
|
| 147 |
+
allow_flagging = "never",
|
| 148 |
+
inputs = [],
|
| 149 |
+
outputs = [
|
| 150 |
+
gr.DataFrame(x="datetime", y="Price prediction [EUR/MWh]")
|
| 151 |
+
# gr.Textbox(label="Date"),
|
| 152 |
+
# gr.Textbox(label="Temperature Forecast [℃]"),
|
| 153 |
+
# gr.Textbox(label="Total Load Forecast [MWh]"),
|
| 154 |
+
# gr.Textbox(label="Total Generation Forecast [MWh]"),
|
| 155 |
+
# gr.Textbox(label="Predicted Day-Ahead Price [EUR/MWh]"),
|
| 156 |
+
]
|
| 157 |
+
)
|
| 158 |
+
|
| 159 |
+
demo.launch()
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
# TODO: we have only the demand predictions for two days ago, so we have two options
|
| 163 |
+
# - skip EIA demand forecast (no comparison)
|
| 164 |
+
# - show prediction for two days ago
|
| 165 |
+
# TODO: allow custom date/temp input (default to today)?
|
| 166 |
+
# TODO: have done some versioning mess (see reqs file)
|
| 167 |
+
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
hopsworks
|
| 2 |
+
joblib
|
| 3 |
+
tensorflow
|
| 4 |
+
pandas
|
| 5 |
+
keras
|
| 6 |
+
entsoe
|
| 7 |
+
scikit-learn==1.0.2
|