File size: 4,513 Bytes
c63bfc4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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"}