second version
This commit is contained in:
@@ -21,12 +21,15 @@ SELECT
|
||||
ROUND(SUM(actual_cost_czk), 2) AS actual_cost_czk,
|
||||
ROUND(SUM(deviation_cost_czk), 2) AS total_deviation_czk,
|
||||
-- Počet intervalů s velkými odchylkami (>1kW)
|
||||
COUNT(*) FILTER (WHERE ABS(deviation_grid_w) > 1000) AS high_deviation_count
|
||||
COUNT(*) FILTER (WHERE ABS(deviation_grid_w) > 1000) AS high_deviation_count,
|
||||
ROUND(SUM(green_bonus_czk), 4) AS green_bonus_czk,
|
||||
ROUND(COALESCE(SUM(actual_cost_czk), 0) * -1 + COALESCE(SUM(green_bonus_czk), 0), 2) AS total_revenue_czk
|
||||
FROM ems.audit_interval
|
||||
GROUP BY site_id, date_trunc('day', interval_start AT TIME ZONE 'Europe/Prague');
|
||||
|
||||
COMMENT ON VIEW ems.vw_audit_daily IS
|
||||
'Denní souhrn auditu per lokalita. Energie v kWh, náklady v Kč.
|
||||
total_revenue_czk = -actual_cost_czk + green_bonus_czk (export/síť vs. bonus).
|
||||
Používat pro dashboard denního přehledu a reporty.';
|
||||
|
||||
-- ============================================================
|
||||
|
||||
78
db/views/R__vw_forecast_accuracy.sql
Normal file
78
db/views/R__vw_forecast_accuracy.sql
Normal file
@@ -0,0 +1,78 @@
|
||||
CREATE OR REPLACE VIEW ems.vw_forecast_accuracy_by_lead_time AS
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT
|
||||
site_id,
|
||||
pv_array_id,
|
||||
CASE
|
||||
WHEN lead_time_hours <= 6 THEN '0-6h'
|
||||
WHEN lead_time_hours <= 12 THEN '6-12h'
|
||||
WHEN lead_time_hours <= 24 THEN '12-24h'
|
||||
WHEN lead_time_hours <= 48 THEN '24-48h'
|
||||
ELSE '48h+'
|
||||
END AS lead_time_bucket,
|
||||
COUNT(*) AS slot_count,
|
||||
COUNT(*) FILTER (WHERE actual_power_w > 100) AS daylight_slots,
|
||||
ROUND(AVG(error_pct)
|
||||
FILTER (WHERE actual_power_w > 100), 2) AS avg_error_pct,
|
||||
ROUND(AVG(ABS(error_pct))
|
||||
FILTER (WHERE actual_power_w > 100), 2) AS avg_abs_error_pct,
|
||||
ROUND(STDDEV(error_pct)
|
||||
FILTER (WHERE actual_power_w > 100), 2) AS stddev_error_pct,
|
||||
CASE
|
||||
WHEN AVG(error_pct) FILTER (WHERE actual_power_w > 100) > 10
|
||||
THEN 'nadhodnocuje'
|
||||
WHEN AVG(error_pct) FILTER (WHERE actual_power_w > 100) < -10
|
||||
THEN 'podhodnocuje'
|
||||
ELSE 'ok'
|
||||
END AS bias
|
||||
FROM ems.forecast_accuracy
|
||||
WHERE actual_power_w IS NOT NULL
|
||||
GROUP BY
|
||||
site_id,
|
||||
pv_array_id,
|
||||
CASE
|
||||
WHEN lead_time_hours <= 6 THEN '0-6h'
|
||||
WHEN lead_time_hours <= 12 THEN '6-12h'
|
||||
WHEN lead_time_hours <= 24 THEN '12-24h'
|
||||
WHEN lead_time_hours <= 48 THEN '24-48h'
|
||||
ELSE '48h+'
|
||||
END
|
||||
) bucketed
|
||||
ORDER BY
|
||||
site_id,
|
||||
pv_array_id,
|
||||
CASE lead_time_bucket
|
||||
WHEN '0-6h' THEN 1
|
||||
WHEN '6-12h' THEN 2
|
||||
WHEN '12-24h' THEN 3
|
||||
WHEN '24-48h' THEN 4
|
||||
WHEN '48h+' THEN 5
|
||||
END;
|
||||
|
||||
COMMENT ON VIEW ems.vw_forecast_accuracy_by_lead_time IS
|
||||
'Přesnost FVE forecastu dle lead time (jak daleko předem byl forecast vytvořen).
|
||||
Ignoruje noční sloty (actual < 100W). avg_error_pct > 0 = forecast nadhodnocuje.
|
||||
Po 4+ týdnech dat lze použít pro kalibraci safety_factor v solveru.';
|
||||
|
||||
CREATE OR REPLACE VIEW ems.vw_forecast_accuracy_daily AS
|
||||
SELECT
|
||||
site_id,
|
||||
pv_array_id,
|
||||
DATE(interval_start AT TIME ZONE 'Europe/Prague') AS day,
|
||||
COUNT(*) FILTER (WHERE actual_power_w IS NOT NULL
|
||||
AND actual_power_w > 100) AS daylight_slots,
|
||||
ROUND(SUM(forecast_power_w)::NUMERIC / 4000, 2) AS forecast_kwh,
|
||||
ROUND(SUM(actual_power_w)::NUMERIC / 4000, 2) AS actual_kwh,
|
||||
ROUND((SUM(forecast_power_w) - SUM(COALESCE(actual_power_w,0)))
|
||||
::NUMERIC / NULLIF(SUM(actual_power_w),0) * 100, 2) AS day_error_pct
|
||||
FROM ems.forecast_accuracy
|
||||
GROUP BY
|
||||
site_id,
|
||||
pv_array_id,
|
||||
DATE(interval_start AT TIME ZONE 'Europe/Prague')
|
||||
ORDER BY day DESC;
|
||||
|
||||
COMMENT ON VIEW ems.vw_forecast_accuracy_daily IS
|
||||
'Denní souhrn přesnosti FVE forecastu v kWh. forecast_kwh vs actual_kwh.
|
||||
day_error_pct > 0 = forecast nadhodnotil denní výrobu.';
|
||||
@@ -18,7 +18,13 @@ SELECT DISTINCT ON (t.inverter_id)
|
||||
t.inverter_temp_c,
|
||||
t.operating_mode,
|
||||
t.fault_code,
|
||||
now() - t.measured_at AS data_age
|
||||
now() - t.measured_at AS data_age,
|
||||
t.pv1_power_w,
|
||||
t.pv2_power_w,
|
||||
t.gen_port_power_w,
|
||||
t.batt_charge_today_wh,
|
||||
t.batt_discharge_today_wh,
|
||||
t.run_state
|
||||
FROM ems.telemetry_inverter t
|
||||
JOIN ems.asset_inverter inv ON inv.id = t.inverter_id
|
||||
ORDER BY t.inverter_id, t.measured_at DESC;
|
||||
|
||||
@@ -5,38 +5,80 @@
|
||||
-- =============================================================
|
||||
|
||||
CREATE OR REPLACE VIEW ems.vw_site_effective_price AS
|
||||
WITH cfg_price AS (
|
||||
SELECT
|
||||
smc.site_id,
|
||||
smc.tariff_id,
|
||||
smc.hdo_code_id,
|
||||
smc.system_services_czk_kwh,
|
||||
smc.buy_margin_fixed_czk,
|
||||
smc.buy_margin_percent,
|
||||
smc.sell_margin_fixed_czk,
|
||||
smc.sell_margin_percent,
|
||||
mip.interval_start,
|
||||
mip.interval_end,
|
||||
mip.market_source,
|
||||
mip.buy_raw_price_czk_kwh,
|
||||
mip.sell_raw_price_czk_kwh,
|
||||
(mip.interval_start AT TIME ZONE 'Europe/Prague')::time AS local_prague_time,
|
||||
EXTRACT(DOW FROM mip.interval_start AT TIME ZONE 'Europe/Prague')::integer AS prague_dow
|
||||
FROM ems.market_interval_price mip
|
||||
CROSS JOIN ems.site_market_config smc
|
||||
WHERE smc.valid_from <= mip.interval_start
|
||||
AND (smc.valid_to IS NULL OR smc.valid_to > mip.interval_start)
|
||||
),
|
||||
rated AS (
|
||||
SELECT
|
||||
cp.*,
|
||||
CASE
|
||||
WHEN cp.hdo_code_id IS NOT NULL AND EXISTS (
|
||||
SELECT 1
|
||||
FROM ems.hdo_code_window w
|
||||
WHERE w.hdo_code_id = cp.hdo_code_id
|
||||
AND (
|
||||
w.day_type = 'all'
|
||||
OR (w.day_type = 'workday' AND cp.prague_dow BETWEEN 1 AND 5)
|
||||
OR (w.day_type = 'weekend' AND cp.prague_dow IN (0, 6))
|
||||
)
|
||||
AND w.rate_type = 'VT'
|
||||
AND cp.local_prague_time >= w.window_from
|
||||
AND cp.local_prague_time < w.window_to
|
||||
) THEN 'VT'::text
|
||||
ELSE 'NT'::text
|
||||
END AS rate_type
|
||||
FROM cfg_price cp
|
||||
)
|
||||
SELECT
|
||||
smc.site_id,
|
||||
mip.interval_start,
|
||||
mip.interval_end,
|
||||
mip.market_source,
|
||||
-- Raw ceny
|
||||
mip.buy_raw_price_czk_kwh,
|
||||
mip.sell_raw_price_czk_kwh,
|
||||
-- Marže
|
||||
smc.buy_margin_fixed_czk,
|
||||
smc.buy_margin_percent,
|
||||
smc.sell_margin_fixed_czk,
|
||||
smc.sell_margin_percent,
|
||||
-- Efektivní ceny
|
||||
ROUND(
|
||||
mip.buy_raw_price_czk_kwh
|
||||
+ smc.buy_margin_fixed_czk
|
||||
+ (mip.buy_raw_price_czk_kwh * smc.buy_margin_percent / 100.0),
|
||||
6
|
||||
) AS effective_buy_price_czk_kwh,
|
||||
ROUND(
|
||||
mip.sell_raw_price_czk_kwh
|
||||
+ smc.sell_margin_fixed_czk
|
||||
+ (mip.sell_raw_price_czk_kwh * smc.sell_margin_percent / 100.0),
|
||||
6
|
||||
) AS effective_sell_price_czk_kwh
|
||||
FROM ems.market_interval_price mip
|
||||
CROSS JOIN ems.site_market_config smc
|
||||
WHERE smc.valid_from <= mip.interval_start
|
||||
AND (smc.valid_to IS NULL OR smc.valid_to > mip.interval_start);
|
||||
r.site_id,
|
||||
r.interval_start,
|
||||
r.interval_end,
|
||||
r.market_source,
|
||||
r.buy_raw_price_czk_kwh,
|
||||
r.sell_raw_price_czk_kwh,
|
||||
r.buy_margin_fixed_czk,
|
||||
r.buy_margin_percent,
|
||||
r.sell_margin_fixed_czk,
|
||||
r.sell_margin_percent,
|
||||
ems.fn_effective_buy_price(r.site_id, r.interval_start) AS effective_buy_price_czk_kwh,
|
||||
ems.fn_effective_sell_price(r.site_id, r.interval_start) AS effective_sell_price_czk_kwh,
|
||||
r.rate_type,
|
||||
COALESCE(
|
||||
(
|
||||
SELECT dtr.price_czk_kwh
|
||||
FROM ems.distribution_tariff_rate dtr
|
||||
WHERE dtr.tariff_id = r.tariff_id
|
||||
AND dtr.rate_type = r.rate_type
|
||||
AND dtr.valid_from <= r.interval_start::date
|
||||
AND (dtr.valid_to IS NULL OR dtr.valid_to > r.interval_start::date)
|
||||
ORDER BY dtr.valid_from DESC
|
||||
LIMIT 1
|
||||
),
|
||||
0::numeric
|
||||
) AS dist_rate_czk_kwh,
|
||||
COALESCE(r.system_services_czk_kwh, 0::numeric) AS system_services_czk_kwh
|
||||
FROM rated r;
|
||||
|
||||
COMMENT ON VIEW ems.vw_site_effective_price IS
|
||||
'Efektivní nákupní a prodejní ceny elektřiny per lokalita a 15min interval.
|
||||
Dopočítává marže z site_market_config na raw ceny z market_interval_price.
|
||||
Nezahrnuje data bez platné market_config. Používat pro plánování a audit.';
|
||||
rate_type NT/VT dle HDO oken; dist_rate = variabilní distribuce bez DPH.
|
||||
effective_* z fn_effective_buy_price / fn_effective_sell_price (marže, DPH u nákupu dle tarifu).';
|
||||
|
||||
@@ -11,3 +11,10 @@ GRANT SELECT ON ems.vw_mode_log_recent TO ems_anon;
|
||||
GRANT SELECT ON ems.vw_operating_mode TO ems_anon;
|
||||
GRANT SELECT ON ems.telemetry_inverter_hourly TO ems_anon;
|
||||
GRANT SELECT ON ems.vw_telemetry_hourly_7d TO ems_anon;
|
||||
GRANT SELECT ON ems.telemetry_heat_pump TO ems_anon;
|
||||
GRANT SELECT ON ems.forecast_accuracy TO ems_anon;
|
||||
GRANT SELECT ON ems.vw_forecast_accuracy_by_lead_time TO ems_anon;
|
||||
GRANT SELECT ON ems.vw_forecast_accuracy_daily TO ems_anon;
|
||||
GRANT SELECT ON ems.consumption_baseline_stats TO ems_anon;
|
||||
GRANT SELECT ON ems.market_price_stats TO ems_anon;
|
||||
GRANT SELECT ON ems.tuv_usage_stats TO ems_anon;
|
||||
|
||||
Reference in New Issue
Block a user