ProjV1 / app.py
eforse01's picture
Create app.py
c63bfc4 verified
from fastapi import FastAPI
from apscheduler.schedulers.background import BackgroundScheduler
import pandas as pd
import requests
import xgboost as xgb
from datetime import datetime, timedelta
import os
import matplotlib.pyplot as plt
app = FastAPI()
# Scheduler
scheduler = BackgroundScheduler()
scheduler.start()
# Load the trained model
model = xgb.XGBRegressor()
model.load_model("electricity_price_model.json")
# Constants
WEATHER_API = "https://api.open-meteo.com/v1/forecast"
ELECTRICITY_PRICE_API = "https://www.elprisetjustnu.se/api/v1/prices"
ENERGY_CHARTS_API = "https://api.energy-charts.info/public_power?"
PREDICTIONS_FILE = "predicted_prices.csv"
# Fetch weather data for the next day
def fetch_weather_data_for_tomorrow():
tomorrow = (datetime.now() + timedelta(days=1)).strftime('%Y-%m-%d')
params = {
"latitude": 59.3293,
"longitude": 18.0686,
"daily": "temperature_2m_mean,precipitation_sum,wind_speed_10m_max,wind_direction_10m_dominant",
"start_date": tomorrow,
"end_date": tomorrow,
"timezone": "Europe/Stockholm"
}
response = requests.get(WEATHER_API, params=params)
response.raise_for_status()
data = response.json()["daily"]
return pd.DataFrame(data)
# Fetch energy production data for the current day
def fetch_energy_production_data():
today = datetime.now().strftime('%Y-%m-%d')
params = {"country": "se", "start": today, "end": today}
response = requests.get(ENERGY_CHARTS_API, params=params)
response.raise_for_status()
data = response.json()
if "production_types" in data:
production_data = {
"unix_seconds": data["unix_seconds"],
**{ptype["name"]: ptype["data"] for ptype in data["production_types"]}
}
energy_df = pd.DataFrame(production_data)
energy_df = energy_df.rename(columns={"unix_seconds": "time"})
energy_df["time"] = pd.to_datetime(energy_df["time"], unit="s", errors="coerce").dt.tz_localize(None)
return energy_df
else:
return pd.DataFrame()
# Fetch electricity prices for the current day
def fetch_current_electricity_prices():
today = datetime.now().strftime('%Y/%m-%d')
url = f"{ELECTRICITY_PRICE_API}/{today}_SE3.json"
response = requests.get(url)
response.raise_for_status()
data = response.json()
electricity_df = pd.DataFrame(data)
electricity_df = electricity_df.rename(columns={"time_start": "time"})
electricity_df["time"] = pd.to_datetime(electricity_df["time"], errors="coerce").dt.tz_localize(None)
return electricity_df
# Prepare dataset for prediction
def prepare_prediction_data():
energy_data = fetch_energy_production_data()
electricity_data = fetch_current_electricity_prices()
weather_data = fetch_weather_data_for_tomorrow()
dataset = pd.merge(energy_data, electricity_data, on="time", how="inner")
dataset = pd.merge(dataset, weather_data, on="time", how="outer")
dataset = dataset.dropna()
return dataset
# Predict electricity prices for the next day
def predict_next_day_price():
dataset = prepare_prediction_data()
X = dataset.drop(["SEK_per_kWh", "time"], axis=1, errors="ignore")
predictions = model.predict(X)
dataset["predicted_price"] = predictions
dataset.to_csv(PREDICTIONS_FILE, index=False)
generate_dashboard(dataset)
print("Predictions saved to 'predicted_prices.csv'.")
# Generate a dashboard for visualization
def generate_dashboard(data):
plt.figure(figsize=(10, 6))
plt.plot(data["time"], data["predicted_price"], label="Predicted Price", linestyle="--")
if "SEK_per_kWh" in data.columns:
plt.plot(data["time"], data["SEK_per_kWh"], label="Actual Price")
plt.xlabel("Time")
plt.ylabel("Electricity Price (SEK/kWh)")
plt.title("Electricity Prices: Predicted vs Actual")
plt.legend()
plt.grid()
plt.savefig("dashboard.png")
plt.close()
# Schedule daily updates
scheduler.add_job(predict_next_day_price, "cron", hour=23, minute=59)
# API: Get predictions
@app.get("/predictions")
def get_predictions():
if not os.path.exists(PREDICTIONS_FILE):
return {"error": "Predictions not available"}
predictions = pd.read_csv(PREDICTIONS_FILE)
return predictions.to_dict()
# API: Get dashboard
@app.get("/dashboard")
def get_dashboard():
if not os.path.exists("dashboard.png"):
return {"error": "Dashboard not available"}
return {"dashboard_url": "/dashboard.png"}