scripts/harness/hu1_realistic_eval.py — realistická simulace BESS 128 kWh/36 kW na spotu místo perfect hindsight: D−1 plán přes solve_dispatch_v2 (informační množina = ceny zítřka z OTE D−1 13:30), SoC řetězené mezi dny, parametry baterie/grid z DB site 5 (fn_planning_site_context). Scénáře fix/spot × bez/s baterií, Kč/den po měsících a sezónách, roční projekce, citlivosti (degradace 0.15/0.5/1.0, spread compression −30 %), GAP vs 7denní hindsight. Varianty běží paralelně (ProcessPoolExecutor). HU1 nemá telemetrii → parametrizovaný průmyslový odběr (konstanty v hlavičce, přepsat čísly od majitele); fixní cena = proxy BA81 (--fix-buy). Výsledky (788 dní 2024-04-14…2026-06-12, 2 zimy): D−B (přechod na spot s baterií) −163,6 tis. Kč/rok base, konzervativně −110,1 tis.; léto −629, zima −254 Kč/den, nejhorší měsíc (12/2024) −41 Kč/den — stále úspora. GAP realistic vs hindsight ≈ 0 (ceny jsou D−1 známé) → dřívější horní mez byla nadhodnocená sezónností, ne neznalostí budoucnosti. Doc: docs/studies/hu1-spot-realistic.md (generuje skript, opakovatelné); README harness doplněn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
4.5 KiB
Markdown
85 lines
4.5 KiB
Markdown
# Ekonomický regresní harness (Fáze 0 — „Čistý plánovač“)
|
||
|
||
Nástroje pro objektivní měření ekonomiky plánovače a regresní bránu pro jeho
|
||
dekompozici. Kontext a fáze: viz strategie refaktoru (Fáze 0–4) v paměti
|
||
projektu / plánu „Čistý plánovač“.
|
||
|
||
## Komponenty
|
||
|
||
| Soubor | Účel |
|
||
|--------|------|
|
||
| `extract_fixtures.py` | Stáhne z EMS DB kompletní vstupy plánovače (context + sloty `fn_load_planning_slots_full`) pro zadanou site a pražský den → JSON fixture do `backend/tests/golden/fixtures/`. |
|
||
| `economics_report.py` | Pro rozsah dní spočítá skutečný cashflow (audit_interval) vs. **oracle LP** (perfect hindsight, čistý model bez heuristických penalt) → tabulka GAP per den. |
|
||
| `hu1_realistic_eval.py` | Investiční studie HU1 (hulin-bess): realistická den-po-dni simulace BESS na spotu přes `solve_dispatch_v2` (D−1 informační množina, řetězené SoC), scénáře fix/spot × bez/s baterií, citlivosti, GAP vs hindsight; generuje `docs/studies/hu1-spot-realistic.md`. Perfect-hindsight horní mez: `hu1_bess_study.py`. |
|
||
| `../../backend/tests/test_golden_replay.py` | Pytest gate: replay fixtures přes `solve_dispatch_two_pass`, porovnání s golden snapshoty v `backend/tests/golden/snapshots/`. |
|
||
|
||
## Připojení k DB
|
||
|
||
Všechny skripty čtou DSN v pořadí `--dsn` > `EMS_DB_DSN` > `DB_HOST`/`DB_PORT`/
|
||
`DB_USER`/`DB_PASSWORD`/`DB_NAME` (default lokální docker `127.0.0.1:5432/ems`).
|
||
Čtou pouze (SELECT) — bezpečné proti produkci.
|
||
|
||
```bash
|
||
export EMS_DB_DSN="postgresql://ems_user:***@10.200.200.1:5432/ems"
|
||
```
|
||
|
||
## Golden replay gate (regresní brána dekompozice)
|
||
|
||
```bash
|
||
cd backend
|
||
python3 -m pytest tests/test_golden_replay.py -q # ověření (identity refactor → musí projít)
|
||
GOLDEN_UPDATE=1 python3 -m pytest tests/test_golden_replay.py -q # vědomá změna chování → regenerace
|
||
```
|
||
|
||
Pravidla:
|
||
- **Fáze 1 (dekompozice)**: snapshoty se NIKDY neregenerují — výstup musí být bitově shodný
|
||
(floaty zaokrouhleny na 4 d.m.).
|
||
- **Fáze 2/3 (změny ekonomiky)**: regenerace snapshotů je povolená pouze s odůvodněním
|
||
v commit message a se zlepšeným/nezhoršeným GAPem v `economics_report.py`.
|
||
- Fixtures jsou zmrazené vstupy z reálné DB (konfigurace k datu extrakce, EV sessions
|
||
vynulovány, `operating_mode=AUTO`) — deterministické, bez DB při běhu testu.
|
||
|
||
### Přidání fixture
|
||
|
||
```bash
|
||
python3 scripts/harness/extract_fixtures.py --site-code home-01 --day 2026-06-07 --tag neg_sell_deep
|
||
cd backend && GOLDEN_UPDATE=1 python3 -m pytest tests/test_golden_replay.py -q
|
||
```
|
||
|
||
`--keep-ev` zmrazí do fixture i otevřené EV sessions z doby extrakce (default je
|
||
vynulovat — historické okno bez session). Hodí se pro EV scénáře (deadline,
|
||
měkký cíl / oportunistické nabíjení, min. výkon wallboxu); `meta.keep_ev`
|
||
ve fixture říká, jak byla pořízena.
|
||
|
||
Pokryté scénáře (v4 fixtures): home-01 hluboký neg-sell (sell −1.57, buy −0.89),
|
||
home-01 běžný spot den, BA81 běžný den, KV1 fixní nákup. Při změnách heuristik
|
||
přidávej scénář, který změnu pokrývá.
|
||
|
||
## Ekonomický report (metrika „kolik necháváme na stole“)
|
||
|
||
```bash
|
||
python3 scripts/harness/economics_report.py --site-code home-01 --from 2026-05-12 --to 2026-06-09
|
||
```
|
||
|
||
- **actual** = skutečný cashflow dne z auditu (import × eff. buy − export × eff. sell),
|
||
- **oracle** = dolní mez: čistý MILP se skutečnou PV/spotřebou/cenami (perfect foresight),
|
||
- obojí **SoC-adjusted**: koncový SoC oceněn průměrnou denní nákupní cenou, aby den
|
||
„nevyhrával“ vybitím baterie,
|
||
- **gap = actual − oracle** = chyba forecastu + neefektivita dispatche. Oracle je
|
||
nedosažitelná dolní mez; sleduj TREND gapu (před/po změně plánovače), ne absolutní nulu.
|
||
|
||
Vyloučeno z obou stran: zelený bonus PV B (nezávislý na dispatch rozhodnutích),
|
||
přesouvání EV/TČ zátěže (spotřeba je brána jako fixní).
|
||
|
||
## Známý stav k 2026-06-11 (baseline)
|
||
|
||
- `tests/test_planning_dispatch_milp.py`: **4 ze 124 testů failují už na main**
|
||
(`test_future_neg_buy_evening_export_at_high_soc_relaxed_prep`,
|
||
`test_grid_charge_respects_import_and_battery_caps`,
|
||
`test_morning_exports_pv_when_cushion_ok`,
|
||
`test_evening_reserve_soc_near_reserve_after_discharge`) — všechny z neg-sell/prep
|
||
heuristik. Nezakrývat regenerací; vyřešit ve Fázi 1/2.
|
||
- Golden snapshot home-01 neg-sell dne: `penalty_czk = 2119 Kč` při cashflow −163 Kč —
|
||
heuristické penalty v objective 13× převažují reálné peníze. To je kvantifikace
|
||
problému, který Fáze 2/3 odstraňují.
|