planner v2 vc. porovnani
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-15 23:03:32 +02:00
parent d89d8b1e3a
commit 7490ac3d70
11 changed files with 900 additions and 29 deletions

View File

@@ -541,6 +541,8 @@ a nechal si kapacitu na nabití v oknech záporných cen.
PLANNING_SOLVER_TIME_LIMIT_SEC=10 # HiGHS timeout
PLANNING_CURTAILMENT_PENALTY=0.001 # Kč/Wh penalizace za omezení FVE
PLANNING_HP_RELAXATION_THRESHOLD=0.3 # pod 30% rated = OFF při post-processingu
PLANNING_ENGINE_VERSION=v1 # v1 = původní planner, v2 = nová policy větev
PLANNING_ENGINE_COMPARE_ENABLED=false # true = spočítat i druhou verzi a uložit comparison do solver_params
```
> **Zelený bonus:** Sazba a platnost jsou v `ems.asset_pv_array` (`green_bonus_*`). Bonus **není** v objective function LP solveru jako aditivní konstanta k nákladům by optimalizaci stejně neměnil. Příjem z bonusu se počítá v **`fn_fill_audit_interval`** přes `ems.fn_green_bonus_revenue()` a ukládá se do `audit_interval.green_bonus_czk`; v přehledech (např. `vw_audit_daily`) je samostatná položka příjmů vedle nákladů ze sítě. Viz `docs/04-modules/market-prices.md` → sekce Zelený bonus.
@@ -565,3 +567,103 @@ highspy>=1.7.0 # HiGHS Python binding (rychlejší než HiGHS_CMD)
- [ ] EV rozdělení výkonu mezi 2 nabíječky zatím řešeno jako agregát
- [ ] Curtailment pole A ověřit Modbus registr pro Output Power Limit na Deye SUN-20K
- [ ] Testovat solver na reálných datech ověřit čas výpočtu pro 36h horizont (144 slotů)
---
## Planner v2
Tahle sekce popisuje návrh druhé verze planneru. Cíl je mít samostatný solver, který bude vycházet ze stejného vstupu a bude zapisovat do stejného `planning_interval`, ale provozní pravidla budou čitelné a striktně dané zadáním.
### Význam hranic SoC
- `reserve_soc_percent` = ranní cílová hranice, na kterou se má baterie dobít, pokud to denní forecast a ceny umožňují
- `min_soc_percent` = fyzická / TOU podlaha, pod kterou baterie nesmí klesnout
- `reserve_soc_percent` je tedy provozní kotva pro den, zatímco `min_soc_percent` je tvrdé minimum
- `reserve_soc_percent` není predikce noční spotřeby; jen znamená „než začne export z FVE do sítě, drž baterii aspoň sem“
### Základní pravidla v2
#### Ráno
- pokud denní forecast dává dostatek výroby nebo levných hodin, planner dobije baterii minimálně na `reserve_soc_percent`
- tato rezerva slouží jako ochrana proti neplánované spotřebě během dne
- `min_soc_percent` se v ranní fázi nepoužívá jako cíl, ale jen jako spodní limit
#### Záporná nákupní cena
- při `buy_price < 0` má prioritu nabíjení ze sítě
- cílem je uložit levnou energii pro pozdější dražší prodej
- to ale neznamená, že se má baterie dobít hned v první záporné hodině; pokud jsou v horizontu ještě zápornější ceny, může být lepší nabíjet později
- nabíjení ze sítě je omezené jen fyzickými limity baterie a připojení
#### Záporná prodejní cena
- při `sell_price < 0` je export do sítě zakázán
- řiditelná FVE A se může škrtit
- neřiditelná FVE B se neškrtí, pouze se povinně zohlední v bilanci
- baterie se nejdřív nabíjí z přebytku FVE, potom se využije flexibilní spotřeba
- pokud je potřeba uvolnit místo pro pozdější extrémně záporné ceny, může planner baterii předem záměrně mírně vybít až na bezpečnou ekonomickou podlahu
#### Nezáporná prodejní cena
- věta „prodám vše“ v tomto návrhu neznamená povinné okamžité vybití baterie
- znamená pouze to, že pokud je baterie už plná z levných nebo záporných hodin, přebytek FVE A jde do sítě
- pokud ještě dává větší smysl uložit energii pro pozdější dražší prodej, má přednost uložení do baterie
- dynamické zátěže jako TUV a wallbox zůstávají plně součástí bilance; jejich spotřeba může být využita jako další „úložiště“ levné energie
#### Prodej z baterie
- při cenové špičce má baterie prodávat do sítě
- v2 má využít baterii jako arbitrážní zásobník mezi levnými a drahými okny
- vybíjení nesmí klesnout pod `min_soc_percent`
#### PV A a PV B
- PV A je řiditelná a může být curtailovaná
- PV B je neřiditelná a nikdy se neplánuje jako curtailovaná výroba
- PV B je vždy pevný vstup do bilance
#### BA81 / GEN cutoff
- v lokalitě BA81 může být zapnutý `deye_gen_microinverter_cutoff_enabled`
- pokud by při záporné prodejní ceně nebo no-export politice vznikal nežádoucí export z GEN portu, planner v2 musí umět aktivovat cutoff mikroinvertoru
- cutoff má být součást rozhodnutí planneru, ne dodatečná heuristika v exporteru
### Co má být v plánu zapsané
Planner v2 má do `planning_interval` zapisovat stejné základní položky jako dosavadní verze:
- `battery_setpoint_w`
- `battery_soc_target_pct`
- `grid_setpoint_w`
- `export_limit_w`
- `export_mode`
- `deye_physical_mode`
- `deye_gen_cutoff_enabled`
- `pv_a_curtailed_w`
- `expected_cost_czk`
- `effective_buy_price`
- `effective_sell_price`
### Implementační oddělení od v1
- v1 zůstává beze změny
- v2 bude samostatný modul planneru
- přepnutí mezi v1 a v2 bude na úrovni orchestrace nebo konfigurace lokality
- exportér i control pipeline mají dál číst standardní výstup z `planning_interval`
- pokud je zapnuté `PLANNING_ENGINE_COMPARE_ENABLED`, backend spočítá obě verze nad stejným vstupem, aktivní verzi zapíše do plánu a druhou uloží i jako samostatný read-only `planning_run` se stavem `comparison`
- compare čtení jde přes `GET /api/v1/sites/{site_id}/plan/compare` a endpoint páruje compare run na aktivní run přes `comparison_of_run_id`
- FE stránka `frontend/src/pages/Planning.tsx` ukazuje souhrn aktivní verze, compare verze, slotové rozdíly a compare křivku baterie v grafu
- fyzicky se na střídač aplikuje jen aktivní plán; compare běh slouží jen pro audit a vizualizaci
### Shrnutí v jedné větě
Planner v2 má dělat přesně toto:
- ráno držet baterii na `reserve_soc_percent`
- při záporných nákupních cenách nabíjet ze sítě
- při záporných prodejních cenách zakázat export
- při cenových špičkách prodávat z baterie
- PV A škrtit jen když je to nutné
- PV B nikdy neškrtit
- BA81 řešit přes GEN cutoff