Files
ems/docs/planning-changelog.md
Dusan Vojacek dbc004a949
Some checks failed
CI and deploy / migration-check (push) Failing after 13s
CI and deploy / deploy (push) Has been skipped
fix refaktoru
2026-05-23 22:20:25 +02:00

99 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Planning / LP — changelog
Změny v plánovači (`planning_engine.py`, `R__063_fn_load_planning_slots_full.sql`) a souvisejících testech.
Formát: **datum (ISO)** · stručný důvod · soubory · chování / ověření.
---
## 2026-05-24 — Arbitráž: OTE místo hodin, export ve špičkách, FVE při sell<0
**Problém:** Plán ukazoval slabé nabíjení/vybíjení (KV1, BA81) přestože ekonomika (OTE) favorizovala opak. Ve špičkách MILP nevybíjel baterii naplno; noc BA81 držela SoC na rezervě bez exportu; záporný výkup neplnil FVE do baterie.
**Změny:**
| Oblast | Co | Proč |
|--------|-----|------|
| **R__063 — exportní maska** | Místo pevného vyloučení **0004** na den prvního `sell<0`: slot vynechat z rozpočtu Wh jen pokud **existuje pozdější slot tentýž den** (před prvním `sell<0`) s `sell > sell_slot + degradace`. | Řídit se **OTE cenami**, ne hodinami. BA81 noc může exportovat; home-01 půlnoc se vynechá, pokud je lepší sell ráno. |
| **R__063 — fixní tarif** | Discharge kandidáti: `sell > buy + degradace` (ne jen `sell > degradace`). | U BA81/KV1 export jen když je výkup nad fixním nákupem. |
| **R__063 — PV vrstva A** | `allow_charge` z FVE při `sell < 0` **bez** filtru `future_sell_lookahead`; filtr „drž na večerní peak“ jen pro `sell ≥ 0`. | V záporném výkupním okně nabít z FVE (KV1 `block_export`). |
| **LP — export shortfall** | Penalizace nevyužitého exportu na **`ge_bat`**, ne na `ge`; pro **všechny** `allow_discharge_export` sloty s kladnou marží (`sell > acquisition` resp. `sell > buy + degrad` u fixed). | Dříve jen `high_sell_slot` (globální max lookahead) → většina večerních slotů bez tlaku na vývoz. |
| **LP — ge_bat push** | Min. ~8 kW export z baterie ve **všech** ekonomicky výhodných discharge slotech (ne jen večer/ráno seznam). | Plán má odpovídat „vylije co dá síť“ ve špičkách. |
| **LP — záporný sell + block_export** | `charge_slots` rozšířeny o sloty `sell<0` s PV přebytkem; měkká penalizace `pv_charge_shortfall` (`bc_pv` vs přebytek FVE). | Postupné nabíjení / curtail místo plné FVE do baterie. |
**Soubory:** `db/routines/R__063_fn_load_planning_slots_full.sql`, `backend/services/planning_engine.py`, `backend/tests/test_planning_charge_slot_selection.py`, `docs/04-modules/planning.md`.
**Neměněno (záměrně):**
- `reserve_soc_percent` u BA81 (**30 %**) — podlaha pro **prodej do sítě**; pod ní jen dům. Noc držela 30 % kvůli **zakázanému exportu v masce**, ne kvůli špatné rezervě.
- Ranní export 511 před `sell<0`, večerní peak ≥17, kotva SoC — beze změny.
**Ověření po deployi:**
1. Flyway repeatable `R__063` + restart backendu.
2. Rolling replan BA81 / KV1 / home-01.
3. MCP: noc BA81 — `allow_discharge_export=true` kde není lepší sell později; večer `abs(battery_setpoint_w)` řádově kW u slotů s `export_mode=BATTERY_SELL`.
4. `pytest backend/tests/test_planning_dispatch_milp.py backend/tests/test_planning_charge_slot_selection.py`
---
## 2026-05-24 (b) — Po deployi: export stále slabý (oprava #2)
**Problém:** Po prvním deployi MCP stále `max_discharge ~300 W`, KV1 `allow_charge=false` při `sell<0`, 0× `BATTERY_SELL` u BA81/KV1. home-01 částečně OK (backend běží).
**Příčiny z MCP:**
1. **Flyway `R__063` neaplikovaný** na DB → masky bez `allow_charge` u záporného výkupu (`ch_true=0` na celém runu KV1).
2. **Fixed marže:** `_slot_profitable_battery_export` používal `buy` v slotu (predikce 4,08 Kč) místo **`charge_acquisition`** (~3,09) → večerní export vypnutý i při `sell` 3,7.
3. **`ge_bat ≤ max_export × z_export`:** solver volil `z_export=0``ge_bat=0` navzdory push.
4. **Safety SoC floor** (~91 %) na ne-high-sell večerních slotech → téměř žádný export.
**Opravy:**
| Změna | Soubor |
|--------|--------|
| Explicitní `allow_charge` pro `sell<0` + `pv_surplus>0` | `R__063` |
| Marže exportu: vždy `sell > acquisition + degrad` | `planning_engine._slot_profitable_battery_export` |
| `ge_bat` push bez násobení `z_export`; `z_export ≥ ge_bat/max_export` | `solve_dispatch` |
| Safety export floor ne na `profitable_export_ts` | `solve_dispatch` |
| Tvrdé `bc_pv ≥ 0.9×pv_surplus` v `charge_slots` + `sell<0` | `solve_dispatch` |
| Penalizace shortfall 40 / 25 Kč/kWh | konstanty |
**Deploy checklist (povinné obojí):**
```bash
# 1) SQL masky
flyway migrate # nebo deploy skript s R__063
# 2) Backend
docker compose build ems-api && docker compose up -d ems-api
# rolling replan nebo počkat :15
```
**Ověření v MCP:**
```sql
-- musí být > 0 po novém runu KV1:
select count(*) from ems.planning_run pr,
jsonb_array_elements(pr.solver_params->'masks') m
where pr.site_id=4 and pr.status='active'
and (m->>'allow_charge')::boolean
and (select effective_sell_price from ems.planning_interval pi
where pi.run_id=pr.id and pi.interval_start=(m->>'slot')::timestamptz) < 0;
```
---
## Šablona pro další záznamy
```markdown
## YYYY-MM-DD — Krátký titul
**Problém:**
**Změny:**
**Soubory:**
**Ověření:**
```