tune korekce z clear sky
This commit is contained in:
@@ -64,19 +64,101 @@ as $fn$
|
||||
(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
|
||||
) / 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
|
||||
from best b
|
||||
cross join tz
|
||||
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 (
|
||||
select
|
||||
s.slot_of_day,
|
||||
(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
|
||||
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
|
||||
and (s.actual_total_w > b.threshold_w or s.forecast_total_w > b.threshold_w)
|
||||
),
|
||||
@@ -119,4 +201,4 @@ as $fn$
|
||||
$fn$;
|
||||
|
||||
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.';
|
||||
|
||||
Reference in New Issue
Block a user