prepsani s opusem dle planu
This commit is contained in:
@@ -32,7 +32,11 @@ returns table (
|
||||
future_sell_opportunity_czk_kwh numeric,
|
||||
is_daytime_pv_surplus_slot boolean,
|
||||
charge_acquisition_buy_czk_kwh numeric,
|
||||
charge_acquisition_cutoff_at timestamptz
|
||||
charge_acquisition_cutoff_at timestamptz,
|
||||
min_buy_before_cutoff_czk_kwh numeric,
|
||||
pv_charge_wh_ahead numeric,
|
||||
neg_buy_wh_ahead numeric,
|
||||
grid_charge_suppressed_reason text
|
||||
)
|
||||
language plpgsql
|
||||
volatile
|
||||
@@ -92,6 +96,14 @@ declare
|
||||
v_est_pv_cost numeric;
|
||||
v_export_window_start timestamptz;
|
||||
v_plan_day_prague date;
|
||||
v_acq_v2 numeric;
|
||||
v_acq_prev numeric := -999;
|
||||
v_iter int;
|
||||
v_affected int;
|
||||
v_cum_allowed numeric;
|
||||
v_pv_ahead_total numeric;
|
||||
v_target_deficit numeric;
|
||||
r_unlock record;
|
||||
begin
|
||||
v_plan_day_prague := (p_from at time zone 'Europe/Prague')::date;
|
||||
drop table if exists _ems_plan_slot_wk;
|
||||
@@ -310,7 +322,11 @@ begin
|
||||
add column if not exists buy_min_next_n numeric,
|
||||
add column if not exists store_score numeric,
|
||||
add column if not exists allow_grid_charge boolean default false,
|
||||
add column if not exists export_window_start_at timestamptz;
|
||||
add column if not exists export_window_start_at timestamptz,
|
||||
add column if not exists min_buy_before_cutoff numeric,
|
||||
add column if not exists pv_charge_wh_ahead numeric,
|
||||
add column if not exists neg_buy_wh_ahead numeric,
|
||||
add column if not exists grid_charge_suppressed_reason text;
|
||||
|
||||
-- První výkupní okno **per kalendářní den** (Prague). Globální min přes dny by
|
||||
-- zablokoval NT grid nabíjení (včerejší večerní peak → dnešní 00–06 už „po okně“).
|
||||
@@ -512,6 +528,127 @@ begin
|
||||
update _ems_plan_slot_wk wk
|
||||
set allow_charge = true, allow_grid_charge = true
|
||||
where wk.buy_price < 0;
|
||||
|
||||
-- Self-konzistentni filtr vrstvy B (spot): vyloucit drahe grid sloty, pokud PV / buy<0
|
||||
-- alternativa pokryje deficit SoC pred prvnim exportem.
|
||||
update _ems_plan_slot_wk wk
|
||||
set pv_charge_wh_ahead = sub.pv_wh_ahead,
|
||||
neg_buy_wh_ahead = sub.neg_buy_wh_ahead,
|
||||
min_buy_before_cutoff = sub.min_buy_ahead
|
||||
from (
|
||||
select
|
||||
wk.slot_ord,
|
||||
least(
|
||||
coalesce(sum(
|
||||
case
|
||||
when w2.slot_ord >= wk.slot_ord
|
||||
and (v_first_neg_sell_ord is null or w2.slot_ord < v_first_neg_sell_ord)
|
||||
and w2.pv_surplus_w > 0
|
||||
and (w2.sell_price < 0 or w2.buy_price < 0)
|
||||
then least(w2.pv_surplus_w::numeric, v_max_charge_w)
|
||||
* v_charge_eff * 0.25
|
||||
else 0
|
||||
end
|
||||
), 0),
|
||||
v_soc_max_wh - p_current_soc_wh
|
||||
) as pv_wh_ahead,
|
||||
coalesce(sum(
|
||||
case
|
||||
when w2.slot_ord >= wk.slot_ord
|
||||
and (v_first_neg_sell_ord is null or w2.slot_ord < v_first_neg_sell_ord)
|
||||
and w2.buy_price < 0
|
||||
then v_per_slot_charge_wh
|
||||
else 0
|
||||
end
|
||||
), 0) as neg_buy_wh_ahead,
|
||||
min(
|
||||
case
|
||||
when w2.slot_ord > wk.slot_ord
|
||||
and (v_first_neg_sell_ord is null or w2.slot_ord < v_first_neg_sell_ord)
|
||||
then w2.buy_price
|
||||
else null
|
||||
end
|
||||
) as min_buy_ahead
|
||||
from _ems_plan_slot_wk wk
|
||||
cross join _ems_plan_slot_wk w2
|
||||
group by wk.slot_ord
|
||||
) sub
|
||||
where wk.slot_ord = sub.slot_ord;
|
||||
|
||||
v_iter := 0;
|
||||
loop
|
||||
v_iter := v_iter + 1;
|
||||
exit when v_iter > 5;
|
||||
|
||||
select coalesce(
|
||||
sum(wk.buy_price * v_per_slot_charge_wh)
|
||||
filter (
|
||||
where wk.allow_grid_charge
|
||||
and (v_first_neg_sell_ord is null or wk.slot_ord < v_first_neg_sell_ord)
|
||||
)
|
||||
/ nullif(sum(v_per_slot_charge_wh)
|
||||
filter (
|
||||
where wk.allow_grid_charge
|
||||
and (v_first_neg_sell_ord is null or wk.slot_ord < v_first_neg_sell_ord)
|
||||
), 0),
|
||||
v_ref_buy_czk_kwh
|
||||
)
|
||||
into v_acq_v2
|
||||
from _ems_plan_slot_wk wk;
|
||||
|
||||
exit when abs(v_acq_v2 - v_acq_prev) < 0.05;
|
||||
v_acq_prev := v_acq_v2;
|
||||
|
||||
update _ems_plan_slot_wk wk
|
||||
set allow_charge = false,
|
||||
allow_grid_charge = false,
|
||||
grid_charge_suppressed_reason =
|
||||
case
|
||||
when wk.pv_charge_wh_ahead + wk.neg_buy_wh_ahead
|
||||
>= greatest(0, v_soc_max_wh - p_current_soc_wh) * 0.6
|
||||
then 'cheaper_pv_ahead'
|
||||
else 'cheaper_neg_buy_ahead'
|
||||
end
|
||||
where wk.allow_grid_charge
|
||||
and wk.buy_price > v_acq_v2 - v_degrad_czk_kwh
|
||||
and wk.buy_price >= 0
|
||||
and (
|
||||
wk.pv_charge_wh_ahead + wk.neg_buy_wh_ahead
|
||||
>= greatest(0, v_soc_max_wh - p_current_soc_wh) * 0.6
|
||||
);
|
||||
|
||||
get diagnostics v_affected = row_count;
|
||||
exit when v_affected = 0;
|
||||
end loop;
|
||||
|
||||
select coalesce(sum(v_per_slot_charge_wh) filter (where wk.allow_grid_charge), 0)
|
||||
into v_cum_allowed
|
||||
from _ems_plan_slot_wk wk;
|
||||
|
||||
select coalesce(min(wk.pv_charge_wh_ahead), 0)
|
||||
into v_pv_ahead_total
|
||||
from _ems_plan_slot_wk wk
|
||||
where wk.slot_ord = 0;
|
||||
|
||||
v_target_deficit := greatest(0, v_soc_max_wh - p_current_soc_wh) - v_pv_ahead_total;
|
||||
|
||||
if v_cum_allowed < v_target_deficit * 0.6 then
|
||||
for r_unlock in
|
||||
select wk.slot_ord
|
||||
from _ems_plan_slot_wk wk
|
||||
where wk.grid_charge_suppressed_reason is not null
|
||||
and wk.buy_price < 2 * v_acq_v2
|
||||
order by wk.buy_price, wk.slot_ord
|
||||
loop
|
||||
update _ems_plan_slot_wk wk
|
||||
set allow_charge = true,
|
||||
allow_grid_charge = true,
|
||||
grid_charge_suppressed_reason = 'safety_failsafe_unlock'
|
||||
where wk.slot_ord = r_unlock.slot_ord;
|
||||
v_cum_allowed := v_cum_allowed + v_per_slot_charge_wh;
|
||||
exit when v_cum_allowed >= v_target_deficit * 0.6;
|
||||
end loop;
|
||||
end if;
|
||||
elsif exists (
|
||||
select 1
|
||||
from _ems_plan_slot_wk w2
|
||||
@@ -925,7 +1062,11 @@ begin
|
||||
(
|
||||
extract(hour from w.interval_start at time zone 'Europe/Prague') between 6 and 18
|
||||
and w.pv_surplus_w > 0
|
||||
) as is_daytime_pv_surplus_slot
|
||||
) as is_daytime_pv_surplus_slot,
|
||||
w.min_buy_before_cutoff as min_buy_before_cutoff_czk_kwh,
|
||||
coalesce(w.pv_charge_wh_ahead, 0) as pv_charge_wh_ahead,
|
||||
coalesce(w.neg_buy_wh_ahead, 0) as neg_buy_wh_ahead,
|
||||
w.grid_charge_suppressed_reason
|
||||
from _ems_plan_slot_wk w
|
||||
cross join night_tot nt
|
||||
)
|
||||
@@ -949,7 +1090,11 @@ begin
|
||||
e.future_sell_opportunity_czk_kwh,
|
||||
e.is_daytime_pv_surplus_slot,
|
||||
v_charge_acquisition as charge_acquisition_buy_czk_kwh,
|
||||
v_acquisition_cutoff as charge_acquisition_cutoff_at
|
||||
v_acquisition_cutoff as charge_acquisition_cutoff_at,
|
||||
e.min_buy_before_cutoff_czk_kwh,
|
||||
e.pv_charge_wh_ahead,
|
||||
e.neg_buy_wh_ahead,
|
||||
e.grid_charge_suppressed_reason
|
||||
from enriched e
|
||||
order by e.slot_ord;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user