Files
ems/scripts/harness/README.md
Dusan Vojacek 826c776c34 HU1: realistická studie přechodu na spot (den-po-dni solver_v2, 2 roky OTE)
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>
2026-06-12 21:56:03 +02:00

4.5 KiB
Raw Blame History

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 04) 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 (D1 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.

export EMS_DB_DSN="postgresql://ems_user:***@10.200.200.1:5432/ems"

Golden replay gate (regresní brána dekompozice)

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

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“)

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í.