uprava aby rano prodaval do site pred sell < 0 oknem
Some checks failed
CI and deploy / migration-check (push) Failing after 20s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-05-26 08:29:05 +02:00
parent da79eec077
commit b4e5fc5040
4 changed files with 303 additions and 14 deletions

View File

@@ -50,7 +50,8 @@
**Planner tag v26:** v25 + upřesnění večerního exportu — viz sekce **Večerní export z baterie** níže a changelog v26.
**Planner tag v23:** v22b + **výboj baterie do sítě** před `buy<0` (`_pre_neg_buy_discharge_indices`, sell≥1 Kč/kWh, push `ge_bat` z DB limitů). Viz changelog v23.
V `solve_dispatch` (AUTO): **`charge_slots`** = `allow_charge` z DB + **`buy < 0`** + všechny sloty **`sell < 0`** s PV přebytkem > 500 W (i bez `block_export_on_negative_sell`, BA81). **`pv_charge_shortfall`** / **`NEG_SELL_CURTAIL_PENALTY`** platí v těchto slotech. Při **`sell < 0`** (legacy): safety deficit cílí **`soc_max_wh`**; po posledním **`sell < 0`**: **`post_neg_pv_topup`**. **Planner tag v32:** fázované SoC — viz níže.
- **Záporný výkup — fázované SoC (v32, `2026-05-28-neg-sell-soc-phases-v32`):** Parametry na **`ems.asset_battery`**: `planner_neg_sell_prep_soc_percent` (default **80**), `planner_neg_sell_full_soc_tail_slots` (default **4** = 1 h), `planner_neg_sell_vent_min_sell_czk_kwh` (default **1** u home-01; **NULL** = ventil B jen při plné baterii). **`_neg_sell_day_phases`** (kalendářní den Prague): **prep** = ASAP nabít na prep %; **tail** = poslední N slotů rampa na `soc_max` + volitelný `ge_pv ≤ pv_b` pokud `sell ≥` práh; měkký curtail A (`pv_a_curtailed_w`) při SoC ≥ prep. Realizace na Deye: **reg 340** = forecast curtail; při plné baterii bez curtailu v plánu EMS 340 **nezapisuje** (solar sell off). Legacy: `prep_soc_percent ≥ 100` nebo `tail_slots = 0`. KV1: seed `prep=100`. Ověření: `NegSellSocPhaseTests`, `solver_params.masks[].neg_sell_phase`. U **fixního tarifu** s polem B: **`ge_pv ≤ pv_b`** (ne pv_store **`ge_pv = 0`**). Při **`deye_gen_microinverter_cutoff_enabled`**: **`ge == 0` jen** pokud **`block_export_on_negative_sell`** (KV1), ne kvůli samotnému `z_gen_cutoff` (BA81 musí moci exportovat B při plné baterii). Vstupní **`soc_wh`** z telemetrie se před MILP omezí přes **`_planner_soc_for_solver`** (rezerva ~650 Wh pod `soc_max`, jinak Infeasible při 100 % SoC a dlouhém záporném výkupu). **`planner_build_tag`** v `solver_params`. Changelog: [`docs/planning-changelog.md`](../planning-changelog.md).
- **Záporný výkup — fázované SoC (v32, `2026-05-28-neg-sell-soc-phases-v32`):** Parametry na **`ems.asset_battery`**: `planner_neg_sell_prep_soc_percent` (default **80**), `planner_neg_sell_full_soc_tail_slots` (default **4** = 1 h), `planner_neg_sell_vent_min_sell_czk_kwh` (default **1** u home-01; **NULL** = ventil B jen při plné baterii). **`_neg_sell_day_phases`** (kalendářní den Prague): **prep** = ASAP nabít na prep %; **tail** = poslední N slotů rampa na `soc_max` + volitelný `ge_pv ≤ pv_b` pokud `sell ≥` práh; měkký curtail A (`pv_a_curtailed_w`) při SoC ≥ prep. Realizace na Deye: **reg 340** = forecast curtail; při plné baterii bez curtailu v plánu EMS 340 **nezapisuje** (solar sell off). Legacy: `prep_soc_percent ≥ 100` nebo `tail_slots = 0`. KV1: seed `prep=100`. Ověření: `NegSellSocPhaseTests`, `solver_params.masks[].neg_sell_phase`.
- **Před sell&lt;0 — export FVE s forecast pojistkou (v33):** `_pre_neg_pv_export_forecast_cushion_ok` — export FVE v kladných slotech před prvním `sell<0` jen pokud součet predikovaného PV přebytku v sell&lt;0 okně (týž pražský den) pokryje dobítí na prep SoC (× **1,15**). Jinak LP raději nabíjí z FVE (riziko deště). Při splněné pojistce: `bc_pv=0` v `pre_neg_pv_export_ts`, shortfall na `ge_pv`, penalizace `bc_pv`. `solver_params.inputs.pre_neg_pv_export_forecast_ok`, `pre_neg_pv_export_slots`. Testy `PreNegPvExportForecastTests`. U **fixního tarifu** s polem B: **`ge_pv ≤ pv_b`** (ne pv_store **`ge_pv = 0`**). Při **`deye_gen_microinverter_cutoff_enabled`**: **`ge == 0` jen** pokud **`block_export_on_negative_sell`** (KV1), ne kvůli samotnému `z_gen_cutoff` (BA81 musí moci exportovat B při plné baterii). Vstupní **`soc_wh`** z telemetrie se před MILP omezí přes **`_planner_soc_for_solver`** (rezerva ~650 Wh pod `soc_max`, jinak Infeasible při 100 % SoC a dlouhém záporném výkupu). **`planner_build_tag`** v `solver_params`. Changelog: [`docs/planning-changelog.md`](../planning-changelog.md).
- **Záporná nákupní cena:**
- horní mez `grid_import` zahrnuje `load_baseline_w` + nabíjení/EV/TČ (bez nekonečného importu).
- **Záporná prodejní cena → tvrdý zákaz vývozu (`ge = 0`)** (`planning_engine.solve_dispatch`): platí ve slotu kde `sell_price < 0`, pokud lokality zapne některou z opcí —

View File

@@ -5,6 +5,14 @@ Formát: **datum (ISO)** · stručný důvod · soubory · chování / ověřen
---
## 2026-05-28 — Před sell&lt;0: export FVE jen při dostatečné predikci v záporném okně (v33)
**Problém:** Při kladném sell ráno LP nabíjel na večerní peak (~6,5 Kč) místo exportu (~3 Kč). Uživatel chce export teď, ale ne když forecast v sell&lt;0 okně nestačí na dobítí (déšť).
**Změna (tag `2026-05-28-pre-neg-pv-export-forecast-v33`):** `_pre_neg_pv_export_forecast_cushion_ok` — porovná potřebné Wh na prep SoC (80 %) s odhadem FVE v sell&lt;0 slotech téhož dne (`_neg_sell_day_pv_usable_wh` × margin 1,15). Jen pak `pre_neg_pv_export_ts` + shortfall `ge_pv` + **`bc_pv=0`** (ranní FVE ne do baterie). Jinak staré chování (šetřit na večer / nabít z FVE).
**Ověření:** `pytest … -k PreNegPvExportForecastTests` · `solver_params.inputs.pre_neg_pv_export_forecast_ok`.
## 2026-05-28 — Záporný výkup: fázované SoC a curtail A (v32)
**Problém:** V okně `sell < 0` LP tlačil `soc_max` až na konci; nepraktické pro EV/TČ/oblačnost; curtail A na FE málo viditelný.