dalsi fixy
This commit is contained in:
@@ -64,11 +64,16 @@ declare
|
||||
v_night_buf_pct numeric;
|
||||
v_degrad_czk_kwh numeric;
|
||||
v_ref_buy_czk_kwh numeric;
|
||||
v_ref_buy_am_czk_kwh numeric;
|
||||
v_ref_buy_pm_czk_kwh numeric;
|
||||
v_purchase_pricing_mode text;
|
||||
v_lookahead_slots int := 4;
|
||||
v_grid_charge_cap_am int := 6;
|
||||
v_grid_charge_cap_pm int := 6;
|
||||
v_grid_charge_cap_am int;
|
||||
v_grid_charge_cap_pm int;
|
||||
v_buy_lookahead_eps numeric := 0.05;
|
||||
v_buy_charge_band_czk_kwh numeric := 0.40;
|
||||
v_grid_filled_wh numeric := 0;
|
||||
v_pv_layer_cap_wh numeric;
|
||||
v_grid_slots_am int := 0;
|
||||
v_grid_slots_pm int := 0;
|
||||
v_acquisition_cutoff timestamptz;
|
||||
@@ -268,11 +273,21 @@ begin
|
||||
end if;
|
||||
v_discharge_target_wh := v_exportable * v_discharge_buf;
|
||||
|
||||
-- Referenční nákup pro arbitráž (celý horizont, ne jen allow_charge).
|
||||
-- Referenční nákup: globální min (export brána) + per AM/PM pás (grid nabíjení).
|
||||
select coalesce(min(wk.buy_price), 0)
|
||||
into v_ref_buy_czk_kwh
|
||||
from _ems_plan_slot_wk wk;
|
||||
|
||||
select coalesce(min(wk.buy_price), v_ref_buy_czk_kwh)
|
||||
into v_ref_buy_am_czk_kwh
|
||||
from _ems_plan_slot_wk wk
|
||||
where extract(hour from wk.interval_start at time zone 'Europe/Prague') < 12;
|
||||
|
||||
select coalesce(min(wk.buy_price), v_ref_buy_czk_kwh)
|
||||
into v_ref_buy_pm_czk_kwh
|
||||
from _ems_plan_slot_wk wk
|
||||
where extract(hour from wk.interval_start at time zone 'Europe/Prague') >= 12;
|
||||
|
||||
-- Lookahead min buy (VT→NT) a store_score pro vrstvu A.
|
||||
alter table _ems_plan_slot_wk
|
||||
add column if not exists future_sell_lookahead numeric,
|
||||
@@ -330,45 +345,42 @@ begin
|
||||
v_chg_pm_wh := v_grid_target_wh - v_chg_am_wh;
|
||||
end if;
|
||||
|
||||
-- charge mask: dvě nezávislé vrstvy (tenký anti-mikrocyklus, ekonomika z cen)
|
||||
if v_per_slot_charge_wh > 0 then
|
||||
v_grid_charge_cap_am := greatest(
|
||||
1,
|
||||
least(24, ceil(v_chg_am_wh / v_per_slot_charge_wh)::int)
|
||||
);
|
||||
v_grid_charge_cap_pm := greatest(
|
||||
1,
|
||||
least(24, ceil(v_chg_pm_wh / v_per_slot_charge_wh)::int)
|
||||
);
|
||||
else
|
||||
v_grid_charge_cap_am := 6;
|
||||
v_grid_charge_cap_pm := 6;
|
||||
end if;
|
||||
|
||||
-- charge mask: grid arbitráž (B) před FVE (A); AM/PM rozpočet Wh zůstává 50/50.
|
||||
--
|
||||
-- A) PV-surplus: ranking store_score DESC (future_sell − sell − max(0,buy−sell)).
|
||||
-- Sloty s nejvyšší hodnotou uložení vs export pokrývají charge target.
|
||||
-- Zbylé PV-surplus → allow_charge=false (PV jen do sítě / bc≤surplus v LP).
|
||||
--
|
||||
-- B) Non-PV grid: jen spot, buy ≤ ref_buy+degrad, buy ≤ min(next N)+ε,
|
||||
-- cap K slotů AM/PM; nikdy při sell < buy − degrad (ztrátový slot).
|
||||
-- B) Grid ze sítě: spot, buy v pásmu AM/PM ≤ min(buy v pásmu)+band, lookahead VT→NT;
|
||||
-- i při pv_surplus>0; cap slotů ∝ rozpočet Wh / per_slot_charge_wh.
|
||||
-- A) PV-surplus: store_score DESC, doplní jen zbytek do energy_to_fill po vrstvě B.
|
||||
if v_charge_buf <= 0 then
|
||||
update _ems_plan_slot_wk wk set allow_charge = true;
|
||||
elsif v_energy_to_fill <= 0 then
|
||||
update _ems_plan_slot_wk wk set allow_charge = true;
|
||||
else
|
||||
update _ems_plan_slot_wk wk set allow_charge = false;
|
||||
|
||||
-- A) PV-surplus: nejvyšší store_score (ukládat FVE vs exportovat)
|
||||
v_cum := 0;
|
||||
for r_slot in
|
||||
select wk.slot_ord, wk.pv_surplus_w
|
||||
from _ems_plan_slot_wk wk
|
||||
where wk.pv_surplus_w > 0
|
||||
and wk.sell_price >= wk.buy_price - v_degrad_czk_kwh
|
||||
order by wk.store_score desc nulls last, wk.slot_ord
|
||||
loop
|
||||
exit when v_cum >= v_grid_target_wh;
|
||||
update _ems_plan_slot_wk wk set allow_charge = true where wk.slot_ord = r_slot.slot_ord;
|
||||
v_cum := v_cum + least(r_slot.pv_surplus_w, v_max_charge_w) * v_charge_eff * 0.25;
|
||||
end loop;
|
||||
v_grid_filled_wh := 0;
|
||||
|
||||
if v_purchase_pricing_mode <> 'fixed' then
|
||||
-- B) Non-PV AM: OTE-first, levný buy + lookahead, cap slotů
|
||||
-- B) Grid AM (dříve než PV, vlastní 50 % rozpočtu Wh)
|
||||
v_cum := 0;
|
||||
v_grid_slots_am := 0;
|
||||
for r_slot in
|
||||
select wk.slot_ord
|
||||
from _ems_plan_slot_wk wk
|
||||
where wk.pv_surplus_w <= 0
|
||||
and extract(hour from wk.interval_start at time zone 'Europe/Prague') < 12
|
||||
and wk.buy_price <= v_ref_buy_czk_kwh + v_degrad_czk_kwh
|
||||
where extract(hour from wk.interval_start at time zone 'Europe/Prague') < 12
|
||||
and wk.buy_price <= v_ref_buy_am_czk_kwh + v_buy_charge_band_czk_kwh
|
||||
and (
|
||||
wk.buy_min_next_n is null
|
||||
or wk.buy_price <= wk.buy_min_next_n + v_buy_lookahead_eps
|
||||
@@ -382,16 +394,16 @@ begin
|
||||
v_cum := v_cum + v_per_slot_charge_wh;
|
||||
v_grid_slots_am := v_grid_slots_am + 1;
|
||||
end loop;
|
||||
v_grid_filled_wh := v_grid_filled_wh + v_cum;
|
||||
|
||||
-- B) Non-PV PM
|
||||
-- B) Grid PM
|
||||
v_cum := 0;
|
||||
v_grid_slots_pm := 0;
|
||||
for r_slot in
|
||||
select wk.slot_ord
|
||||
from _ems_plan_slot_wk wk
|
||||
where wk.pv_surplus_w <= 0
|
||||
and extract(hour from wk.interval_start at time zone 'Europe/Prague') >= 12
|
||||
and wk.buy_price <= v_ref_buy_czk_kwh + v_degrad_czk_kwh
|
||||
where extract(hour from wk.interval_start at time zone 'Europe/Prague') >= 12
|
||||
and wk.buy_price <= v_ref_buy_pm_czk_kwh + v_buy_charge_band_czk_kwh
|
||||
and (
|
||||
wk.buy_min_next_n is null
|
||||
or wk.buy_price <= wk.buy_min_next_n + v_buy_lookahead_eps
|
||||
@@ -405,7 +417,23 @@ begin
|
||||
v_cum := v_cum + v_per_slot_charge_wh;
|
||||
v_grid_slots_pm := v_grid_slots_pm + 1;
|
||||
end loop;
|
||||
v_grid_filled_wh := v_grid_filled_wh + v_cum;
|
||||
end if;
|
||||
|
||||
-- A) PV-surplus: jen zbytek kapacity po grid vrstvě B
|
||||
v_pv_layer_cap_wh := greatest(v_energy_to_fill - v_grid_filled_wh, 0);
|
||||
v_cum := 0;
|
||||
for r_slot in
|
||||
select wk.slot_ord, wk.pv_surplus_w
|
||||
from _ems_plan_slot_wk wk
|
||||
where wk.pv_surplus_w > 0
|
||||
and wk.sell_price >= wk.buy_price - v_degrad_czk_kwh
|
||||
order by wk.store_score desc nulls last, wk.slot_ord
|
||||
loop
|
||||
exit when v_cum >= v_pv_layer_cap_wh;
|
||||
update _ems_plan_slot_wk wk set allow_charge = true where wk.slot_ord = r_slot.slot_ord;
|
||||
v_cum := v_cum + least(r_slot.pv_surplus_w, v_max_charge_w) * v_charge_eff * 0.25;
|
||||
end loop;
|
||||
end if;
|
||||
|
||||
-- discharge-export mask
|
||||
@@ -443,6 +471,7 @@ begin
|
||||
from _ems_plan_slot_wk wk
|
||||
where wk.allow_discharge_export;
|
||||
|
||||
-- Acquisition: vážený buy v allow_charge slotech před 1. exportem (ne future_sell z FVE).
|
||||
select
|
||||
coalesce(sum(
|
||||
case
|
||||
@@ -455,17 +484,6 @@ begin
|
||||
else 0
|
||||
end
|
||||
), 0),
|
||||
coalesce(sum(
|
||||
case
|
||||
when wk.pv_surplus_w > 0
|
||||
and (
|
||||
v_acquisition_cutoff is null
|
||||
or wk.interval_start < v_acquisition_cutoff
|
||||
)
|
||||
then least(wk.pv_surplus_w, v_max_charge_w) * v_charge_eff * 0.25
|
||||
else 0
|
||||
end
|
||||
), 0),
|
||||
coalesce(sum(
|
||||
case
|
||||
when wk.allow_charge
|
||||
@@ -476,31 +494,22 @@ begin
|
||||
then wk.buy_price * v_per_slot_charge_wh
|
||||
else 0
|
||||
end
|
||||
), 0),
|
||||
coalesce(sum(
|
||||
case
|
||||
when wk.pv_surplus_w > 0
|
||||
and (
|
||||
v_acquisition_cutoff is null
|
||||
or wk.interval_start < v_acquisition_cutoff
|
||||
)
|
||||
then coalesce(wk.future_sell_lookahead, wk.sell_price)
|
||||
* least(wk.pv_surplus_w, v_max_charge_w) * v_charge_eff * 0.25
|
||||
else 0
|
||||
end
|
||||
), 0)
|
||||
into
|
||||
v_est_grid_wh,
|
||||
v_est_pv_wh,
|
||||
v_est_grid_cost,
|
||||
v_est_pv_cost
|
||||
v_est_grid_cost
|
||||
from _ems_plan_slot_wk wk;
|
||||
|
||||
if (v_est_grid_wh + v_est_pv_wh) > 0 then
|
||||
v_charge_acquisition := (v_est_grid_cost + v_est_pv_cost)
|
||||
/ (v_est_grid_wh + v_est_pv_wh);
|
||||
v_est_pv_wh := 0;
|
||||
v_est_pv_cost := 0;
|
||||
|
||||
if v_est_grid_wh > 0 then
|
||||
v_charge_acquisition := v_est_grid_cost / v_est_grid_wh;
|
||||
else
|
||||
v_charge_acquisition := v_ref_buy_czk_kwh;
|
||||
v_charge_acquisition := coalesce(
|
||||
(v_ref_buy_am_czk_kwh + v_ref_buy_pm_czk_kwh) / 2.0,
|
||||
v_ref_buy_czk_kwh
|
||||
);
|
||||
end if;
|
||||
|
||||
return query
|
||||
@@ -602,5 +611,5 @@ comment on function ems.fn_load_planning_slots_full is
|
||||
'Strop SoC pro výpočet energie k dobití: coalesce(planner_max_soc_percent, max_soc_percent). '
|
||||
'Denní safety vstupy: night_baseload_* (20:00–06:00 Europe/Prague), safety_soc_target_wh (6–19), '
|
||||
'lookahead max buy/sell pro měkké LP penalizace. '
|
||||
'charge_acquisition_buy_czk_kwh: vážený průměr grid (allow_charge) + FVE (pv_surplus, opportunity future_sell) '
|
||||
'jen pro sloty před charge_acquisition_cutoff_at (= začátek prvního allow_discharge_export).';
|
||||
'charge_acquisition_buy_czk_kwh: vážený buy v allow_charge slotech před charge_acquisition_cutoff_at. '
|
||||
'Grid maska B běží před PV vrstvou A; AM/PM rozpočet Wh 50/50; cap slotů z rozpočtu / per_slot_charge_wh.';
|
||||
|
||||
Reference in New Issue
Block a user