-- ============================================================ -- Tabulka pro tracking přesnosti forecastu -- ============================================================ CREATE TABLE ems.forecast_accuracy ( id SERIAL PRIMARY KEY, site_id INT NOT NULL REFERENCES ems.site(id), pv_array_id INT NOT NULL REFERENCES ems.asset_pv_array(id), interval_start TIMESTAMPTZ NOT NULL, run_id INT NOT NULL REFERENCES ems.forecast_pv_run(id), -- Forecast hodnoty forecast_power_w INT NOT NULL, forecast_created_at TIMESTAMPTZ NOT NULL, lead_time_hours NUMERIC(6,2), -- kolik hodin předem byl forecast vytvořen -- Skutečnost (doplněna zpětně z telemetrie) actual_power_w INT, actual_filled_at TIMESTAMPTZ, -- Odchylka error_w INT, -- forecast - actual error_pct NUMERIC(8,4), -- (forecast - actual) / actual * 100 UNIQUE (run_id, interval_start) ); COMMENT ON TABLE ems.forecast_accuracy IS 'Tracking přesnosti FVE forecastu. Každý řádek = jeden 15min slot z jednoho forecast runu. actual_power_w se doplňuje zpětně z telemetrie po uplynutí intervalu přes fn_fill_forecast_accuracy(). Uchovávat navždy – slouží pro analýzu přesnosti a budoucí kalibraci solveru.'; COMMENT ON COLUMN ems.forecast_accuracy.lead_time_hours IS 'Kolik hodin předem byl tento forecast vytvořen. Příklad: forecast vytvořen v pondělí 14:00, interval ve středu 12:00 = 46h. Slouží pro analýzu: je 6h forecast přesnější než 48h forecast?'; COMMENT ON COLUMN ems.forecast_accuracy.error_pct IS 'Relativní chyba v %. Kladná = forecast nadhodnotil, záporná = podhodnotil. NULL pokud actual_power_w = 0 (zamezení dělení nulou).'; CREATE INDEX idx_forecast_accuracy_site_time ON ems.forecast_accuracy (site_id, interval_start DESC); CREATE INDEX idx_forecast_accuracy_array_lead ON ems.forecast_accuracy (pv_array_id, lead_time_hours, interval_start DESC);