tuning BA81
Some checks failed
CI and deploy / migration-check (push) Failing after 13s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-04-26 20:12:28 +02:00
parent 4875c31338
commit 5f96a4cf01
5 changed files with 37 additions and 2 deletions

View File

@@ -577,9 +577,12 @@ def solve_dispatch(
if horizon_slots_h24 > 0
else 4.0
)
terminal_factor = float(
getattr(battery, "planner_terminal_soc_value_factor", TERMINAL_SOC_VALUE_FACTOR)
)
# Kč/Wh: ocenění energie ponechané v baterii na konci horizontu (receding horizon kotva).
terminal_soc_kcz_per_wh = (
avg_buy_terminal * TERMINAL_SOC_VALUE_FACTOR / 1000.0
avg_buy_terminal * terminal_factor / 1000.0
)
# Kotva: poslední slot před prvním sell<0 by měl končit u planner floor (pokud relaxace existuje).
@@ -687,6 +690,11 @@ def solve_dispatch(
if s.sell_price < 0:
prob += w_arb[t] == 0
prob += bd[t] <= pulp.lpSum(ev_via_bat[e][t] for e in range(EV))
# BA81 (GEN port microinverters): pokud máme k dispozici GEN cut-off, držíme skutečný
# BLOCK_EXPORT jako hard constraint: export do sítě v okně se záporným prodejem je zakázaný.
# Přebytek pak řeší curtail PV A / nabíjení / případně GEN cut-off (reg 179).
if z_gen_cutoff is not None:
prob += ge[t] == 0
soc_prev_expr = current_soc_wh if t == 0 else soc[t - 1]
arb_t = arb_floor_series[t]

View File

@@ -0,0 +1,9 @@
alter table ems.asset_battery
add column if not exists planner_terminal_soc_value_factor numeric not null default 0.9;
comment on column ems.asset_battery.planner_terminal_soc_value_factor is
'Váha terminal SoC shadow price v LP solveru.
0 = solver nemá motivaci držet energii v baterii na konci horizontu (agresivnější arbitráž / vybití).
1 = odpovídá ~průměrné nákupní ceně (konzervativní držení energie).
Používá se v backend/services/planning_engine.py (terminal_soc_kcz_per_wh).';

View File

@@ -130,6 +130,13 @@ begin
raise exception 'No site_grid_connection for site_id=%', p_site_id;
end if;
-- LP tuning (battery-level): terminal SoC shadow price factor
v_b := jsonb_set(
v_b,
'{planner_terminal_soc_value_factor}',
to_jsonb(coalesce((v_b->>'planner_terminal_soc_value_factor')::numeric, 0.9))
);
select coalesce(
jsonb_agg(
jsonb_build_object(

View File

@@ -80,7 +80,7 @@ Z toho plyne: **cut-off GEN portu je smysluplné řídit podle očekávaného p
## EMS politiky (nejsou fyzické stavy Deye)
- **PV_SELL_ONLY:** AUTO + constraint solveru `max_discharge_from_pv`
- **BLOCK_EXPORT:** AUTO + záporná sell_price → `ge[t]=0`
- **BLOCK_EXPORT:** AUTO + záporná sell_price → `ge[t]=0` (hard constraint, pokud má lokalita k dispozici GEN port cut-off; jinak solver export jen penalizuje přes zápornou cenu)
- **NEGATIVE_HARVEST:** AUTO + záporná buy_price → max charge/load
- **PROTECT:** SELF_SUSTAIN s konzervativními limity

View File

@@ -471,6 +471,17 @@ COMMENT ON COLUMN ems.planning_interval.pv_a_curtailed_w IS
---
## Tuning pro malé baterie (např. BA81)
Pokud solver „šetří baterku“ a raději importuje ze sítě (kvůli terminal SoC shadow price), lze per baterii upravit váhu této kotvy:
- `ems.asset_battery.planner_terminal_soc_value_factor`
- `0.0` = žádná motivace držet SoC na konci horizontu (agresivnější arbitráž / vybití)
- `0.9` = default (konzervativnější držení energie)
Pro BA81 typicky dává smysl menší hodnota (např. 00.3), aby solver klidně „vylil“ baterii do sítě při kladné `sell_price`
a nechal si kapacitu na nabití v oknech záporných cen.
## Konfigurace (env proměnné)
```env