import pandas as pd import numpy as np import xgboost as xgb import mysql.connector from mysql.connector import Error from datetime import datetime, timedelta # --- CONFIGURATIE --- MODEL_FILE = 'price_forecast_model.json' TARGET = 'gemiddelde_prijs' AANTAL_UUR_VOORSPELLEN = 120 # Hoeveel uur vooruit wil je kijken? pd.set_option('display.max_rows', None) # Forceert pandas om ALLE rijen te printen # --- MySQL Database Config --- # VUL DIT IN MET JOUW GEGEVENS DB_CONFIG = { 'host': '192.168.178.201', 'user': 'energy_prices_user', 'password': 'kS9R*xp17ZwCD@CV&E^N', 'database': 'energy_prices', 'port': 3307 } # Dit zijn de 16 features die het model MOET hebben FEATURES = [ 'temperatuur', 'gevoelstemperatuur', 'neerslag', 'wind_richting', 'wind_snelheid', 'bewolking', 'luchtdruk', 'luchtvochtigheid', 'uur_van_de_dag', 'dag_van_de_week', 'maand', 'dag_van_het_jaar', 'prijs_1u_geleden', 'prijs_24u_geleden', 'temp_avg_3u', 'prijs_avg_6u' ] print("="*70) print("PRIJS VOORSPELLER (op basis van data uit MySQL)") print("="*70) def haal_data_uit_database(conn): """ Haalt alle benodigde data op: 1. Historie (afgelopen 30 uur, weer + prijs) 2. Toekomst (komende 24 uur, alleen weer) """ print("šŸ’¾ Data ophalen uit MySQL...") # 1. Haal recente HISTORIE op (weer + prijs) # We hebben de prijs-tabel (dynamic_price_data) nodig query_hist = """ SELECT w.datum_tijd, w.temperatuur, w.gevoelstemperatuur, w.neerslag, w.wind_richting, w.wind_snelheid, w.bewolking, w.luchtdruk, w.luchtvochtigheid, p_avg.gemiddelde_prijs FROM amersfoort_weer_uurlijks AS w JOIN (SELECT datetime, AVG(price) AS gemiddelde_prijs FROM dynamic_price_data GROUP BY datetime) AS p_avg ON w.datum_tijd = p_avg.datetime WHERE w.datum_tijd BETWEEN (NOW() - INTERVAL 30 HOUR) AND NOW() ORDER BY w.datum_tijd; """ # 2. Haal TOEKOMSTIG weer op (alleen weer, prijs is NULL) query_toekomst = f""" SELECT datum_tijd, temperatuur, gevoelstemperatuur, neerslag, wind_richting, wind_snelheid, bewolking, luchtdruk, luchtvochtigheid, NULL AS gemiddelde_prijs -- Prijs is nog niet bekend FROM amersfoort_weer_uurlijks WHERE datum_tijd BETWEEN NOW() AND (NOW() + INTERVAL {AANTAL_UUR_VOORSPELLEN} HOUR) ORDER BY datum_tijd; """ try: hist_df = pd.read_sql(query_hist, conn, index_col='datum_tijd', parse_dates=['datum_tijd']) toekomst_df = pd.read_sql(query_toekomst, conn, index_col='datum_tijd', parse_dates=['datum_tijd']) print(f"āœ… {len(hist_df)} uur historie geladen.") print(f"āœ… {len(toekomst_df)} uur toekomstig weer geladen.") # 3. Combineer ze tot ƩƩn 'werkblad' combined_df = pd.concat([hist_df, toekomst_df]) return combined_df.sort_index() except Exception as e: print(f"āŒ Fout bij ophalen data: {e}") return None def maak_features_voor_uur(df, timestamp): """ Maak de 16 features voor ƩƩn specifiek uur. Hiervoor zijn de *vorige* rijen in de DataFrame nodig. """ features = {} # Haal data op van het specifieke uur data_nu = df.loc[timestamp] # 1. Tijd-features features['uur_van_de_dag'] = timestamp.hour features['dag_van_de_week'] = timestamp.dayofweek features['maand'] = timestamp.month features['dag_van_het_jaar'] = timestamp.dayofyear # 2. Weer-features (direct uit de data) weer_cols = ['temperatuur', 'gevoelstemperatuur', 'neerslag', 'wind_richting', 'wind_snelheid', 'bewolking', 'luchtdruk', 'luchtvochtigheid'] for col in weer_cols: features[col] = data_nu[col] # 3. Lag-features (van vorige uren) features['prijs_1u_geleden'] = df.loc[timestamp - timedelta(hours=1)]['gemiddelde_prijs'] features['prijs_24u_geleden'] = df.loc[timestamp - timedelta(hours=24)]['gemiddelde_prijs'] # 4. Rolling-features (gemiddelden van vorige uren) features['temp_avg_3u'] = df.loc[timestamp - timedelta(hours=2) : timestamp]['temperatuur'].mean() features['prijs_avg_6u'] = df.loc[timestamp - timedelta(hours=5) : timestamp]['gemiddelde_prijs'].mean() # Converteer naar een DataFrame met de juiste kolomvolgorde return pd.DataFrame([features], columns=FEATURES) # --- START VAN HET SCRIPT --- try: # 1. Laad het getrainde model print(f"Laden van model: {MODEL_FILE}...") model = xgb.XGBRegressor() model.load_model(MODEL_FILE) print("āœ… Model succesvol geladen.") # 2. Maak verbinding met de database conn = mysql.connector.connect(**DB_CONFIG) # 3. Haal alle data op (historie + toekomstig weer) werk_df = haal_data_uit_database(conn) if werk_df is not None: # 4. Zoek de uren die we moeten voorspellen # (Dit zijn de uren waar 'gemiddelde_prijs' NULL is) te_voorspellen_tijden = werk_df[werk_df['gemiddelde_prijs'].isnull()].index print(f"\n🧠 Start iteratieve voorspelling voor {len(te_voorspellen_tijden)} uur...") voorspellingen = [] # 5. De Voed-Terug-Lus for timestamp in te_voorspellen_tijden: # a. Maak features voor dit uur (gebruikt data van vorige uren) features_nu = maak_features_voor_uur(werk_df, timestamp) # b. Maak de voorspelling voorspelde_prijs = model.predict(features_nu)[0] # c. VOED TERUG: Sla de voorspelling op in het 'werkblad' # zodat het volgende uur deze kan gebruiken! werk_df.loc[timestamp, 'gemiddelde_prijs'] = voorspelde_prijs # d. Sla op voor het eindresultaat voorspellingen.append(voorspelde_prijs) # 6. Toon de resultaten print("\n" + "="*70) print(f"--- VOORSPELDE PRIJZEN (komende {len(te_voorspellen_tijden)} uur) ---") resultaat_df = pd.DataFrame({ 'Voorspelde_Prijs': voorspellingen }, index=te_voorspellen_tijden) print(resultaat_df) print("="*70) except Error as e: print(f"āŒ Fout met MySQL verbinding: {e}") except FileNotFoundError: print(f"āŒ Fout: Model bestand '{MODEL_FILE}' niet gevonden.") except Exception as e: print(f"āŒ Een onverwachte fout is opgetreden: {e}") finally: if 'conn' in locals() and conn.is_connected(): conn.close() print("\nVerbinding met MySQL gesloten.")