tune korekce z clear sky
Some checks failed
CI and deploy / migration-check (push) Failing after 10s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-04-22 20:17:29 +02:00
parent 09f1d2de68
commit 638c5444be
2 changed files with 86 additions and 4 deletions

View File

@@ -64,19 +64,101 @@ as $fn$
(extract(hour from (b.interval_start at time zone tz.tz_name))::int * 60) (extract(hour from (b.interval_start at time zone tz.tz_name))::int * 60)
+ extract(minute from (b.interval_start at time zone tz.tz_name))::int + extract(minute from (b.interval_start at time zone tz.tz_name))::int
) / 15 as slot_of_day, ) / 15 as slot_of_day,
(b.interval_start at time zone tz.tz_name)::date as day_local,
extract(epoch from (now() - b.interval_start)) / 86400.0 as age_days extract(epoch from (now() - b.interval_start)) / 86400.0 as age_days
from best b from best b
cross join tz cross join tz
where b.rn = 1 where b.rn = 1
group by b.interval_start, slot_of_day, tz.tz_name group by b.interval_start, slot_of_day, day_local, tz.tz_name
),
-- Denní „clear-ish“ skóre: preferujeme dny s hladkou křivkou výroby a vysokou denní energií
-- relativně k ostatním dnům v okně (mraky dělají vysokofrekvenční šum na 15min, který není dobrý anchor pro slot bias).
day_energy as (
select
s.day_local,
sum(s.actual_total_w)::numeric / 4000.0 as energy_kwh
from slots s
group by s.day_local
),
ref as (
select percentile_cont(0.5) within group (order by de.energy_kwh) as med_kwh
from day_energy de
),
slot_steps as (
select
s.*,
lag(s.actual_total_w) over (partition by s.day_local order by s.interval_start) as prev_actual_w
from slots s
where s.slot_of_day between 20 and 80
and s.actual_total_w > (select threshold_w from bounds)
),
day_jump as (
select
ss.day_local,
percentile_cont(0.5) within group (order by abs(ss.actual_total_w - ss.prev_actual_w)) as med_jump_w
from slot_steps ss
where ss.prev_actual_w is not null
group by ss.day_local
),
day_med as (
select
s.day_local,
percentile_cont(0.5) within group (order by s.actual_total_w) as p50_actual_w
from slots s
where s.actual_total_w > (select threshold_w from bounds)
group by s.day_local
),
day_stats as (
select
de.day_local,
de.energy_kwh,
dj.med_jump_w,
dm.p50_actual_w,
case
when (select med_kwh from ref) is null or (select med_kwh from ref) <= 0 then 0.5
else greatest(
0.0,
least(
1.0,
(de.energy_kwh - (select med_kwh from ref) * 0.55)
/ nullif((select med_kwh from ref) * 0.35, 0)
)
)
end as w_energy,
case
when dj.med_jump_w is null or dm.p50_actual_w is null then 0.35
else greatest(
0.0,
least(
1.0,
1.0
- (
dj.med_jump_w
/ nullif(greatest(300.0, dm.p50_actual_w * 0.25), 0)
)
)
)
end as w_smooth
from day_energy de
left join day_jump dj on dj.day_local = de.day_local
left join day_med dm on dm.day_local = de.day_local
), ),
filtered as ( filtered as (
select select
s.slot_of_day, s.slot_of_day,
(s.forecast_total_w - s.actual_total_w) as error_w, (s.forecast_total_w - s.actual_total_w) as error_w,
exp(-s.age_days / nullif((select half_life_days from bounds), 0)) as w exp(-s.age_days / nullif((select half_life_days from bounds), 0))
* (
0.05
+ 0.95
* greatest(
0.0,
least(1.0, coalesce(ds.w_energy, 0.35) * coalesce(ds.w_smooth, 0.35))
)
) as w
from slots s from slots s
cross join bounds b cross join bounds b
left join day_stats ds on ds.day_local = s.day_local
where s.slot_of_day between 0 and 95 where s.slot_of_day between 0 and 95
and (s.actual_total_w > b.threshold_w or s.forecast_total_w > b.threshold_w) and (s.actual_total_w > b.threshold_w or s.forecast_total_w > b.threshold_w)
), ),
@@ -119,4 +201,4 @@ as $fn$
$fn$; $fn$;
comment on function ems.fn_pv_forecast_delta_profile(int, timestamptz, timestamptz, numeric, int) is comment on function ems.fn_pv_forecast_delta_profile(int, timestamptz, timestamptz, numeric, int) is
'Aditivní delta profil chyby PV forecastu po 15min slotu dne (96 slotů). Zdroj: forecast_accuracy, vážení exp(-age/half_life_days). Vrací JSON {deltas:[{slot_of_day, delta_w, sample_count}], ...}. Interní minimální cutoff dat (2026-04-06 Europe/Prague) brání učení z nekonzistentní historie před kompletním plněním actual.'; 'Aditivní delta profil chyby PV forecastu po 15min slotu dne (96 slotů). Zdroj: forecast_accuracy, vážení exp(-age/half_life_days) * day_weight (preferuje „clear-ish“ dny: vyšší denní energie vs median v okně + nižší median skoků výkonu mezi 15min v daylight bandu). Vrací JSON {deltas:[{slot_of_day, delta_w, sample_count}], ...}. Interní minimální cutoff dat (2026-04-11 Europe/Prague) brání učení z nekonzistentní historie před kompletním plněním actual.';

View File

@@ -18,7 +18,7 @@ Shrnutí otevřených bodů z `docs/06-open-questions.md`, checklistů v modulec
| **Telemetry výroba FVE:** Registry 672/673/667 jsou **signed** W; `pv_power_w` = max(0,pv1)+max(0,pv2)+max(0,gen) (dashboard); sloupce pv1/pv2/gen ukládají signed pro audit. | | **Telemetry výroba FVE:** Registry 672/673/667 jsou **signed** W; `pv_power_w` = max(0,pv1)+max(0,pv2)+max(0,gen) (dashboard); sloupce pv1/pv2/gen ukládají signed pro audit. |
| **Ekonomika baterie:** snížení `reserve_soc_percent` na 10 % a `degradation_cost_czk_kwh` na 0.1500 (migrace `V026__battery_economics_tuning.sql`), úpravy objective pro ekonomicky konzistentnější nabíjení/vybíjení. | | **Ekonomika baterie:** snížení `reserve_soc_percent` na 10 % a `degradation_cost_czk_kwh` na 0.1500 (migrace `V026__battery_economics_tuning.sql`), úpravy objective pro ekonomicky konzistentnější nabíjení/vybíjení. |
| **Planning UI operátor akce:** trvale viditelné akce import/forecast/init plan, volba data OTE (dnes/zítra), zobrazení `pv_scarcity_factor` ve stavu plánu. | | **Planning UI operátor akce:** trvale viditelné akce import/forecast/init plan, volba data OTE (dnes/zítra), zobrazení `pv_scarcity_factor` ve stavu plánu. |
| **PV delta profil cutoff historie:** po analýze `ems.forecast_accuracy` pro `home-01` je minimální spolehlivý začátek učení **2026-04-06 (Europe/Prague)** (UTC `2026-04-05T22:00:00Z`); cutoff je zafixovaný v `db/routines/R__078_fn_pv_forecast_delta_profile.sql` (ignoruje starší data i při širším `p_data_from`). | | **PV delta profil cutoff historie:** po analýze `ems.forecast_accuracy` pro `home-01` je minimální spolehlivý začátek učení **2026-04-11 (Europe/Prague)** (UTC `2026-04-10T22:00:00Z`); cutoff je zafixovaný v `db/routines/R__078_fn_pv_forecast_delta_profile.sql` (ignoruje starší data i při širším `p_data_from`). |
--- ---