From b844a9182f18372d33f7d806a18004afe4dae924 Mon Sep 17 00:00:00 2001 From: Dusan Vojacek Date: Sun, 24 May 2026 23:19:54 +0200 Subject: [PATCH] dalsi fix home-01 --- backend/services/planning_engine.py | 3 +++ backend/tests/test_planning_charge_slot_selection.py | 8 +++++--- db/routines/R__063_fn_load_planning_slots_full.sql | 5 +++++ docs/05-todo.md | 4 ++++ docs/planning-changelog.md | 10 ++++++++++ 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/backend/services/planning_engine.py b/backend/services/planning_engine.py index f602aca..4097190 100644 --- a/backend/services/planning_engine.py +++ b/backend/services/planning_engine.py @@ -619,6 +619,9 @@ def _recompute_charge_acquisition_from_results( for s, r in zip(slots, results): if not s.allow_charge: continue + # Zaporne buy sloty (OTE) nejsou grid acquisition pro arbitraz exportu baterie. + if float(s.buy_price) < 0: + continue gi_w = max(0, int(r.grid_setpoint_w or 0)) bc_w = max(0, int(r.battery_setpoint_w or 0)) wh = (gi_w + bc_w) * INTERVAL_H diff --git a/backend/tests/test_planning_charge_slot_selection.py b/backend/tests/test_planning_charge_slot_selection.py index 8b55f92..e82009b 100644 --- a/backend/tests/test_planning_charge_slot_selection.py +++ b/backend/tests/test_planning_charge_slot_selection.py @@ -129,10 +129,12 @@ def _apply_dynamic_grid_filter( if not remaining: break total_wh = len(remaining) * per_slot_wh - if total_wh <= 0: - acq = min(float(s.buy_price) for s in slots) + pos_remaining = [t for t in remaining if float(slots[t].buy_price) >= 0] + total_wh_pos = len(pos_remaining) * per_slot_wh + if total_wh_pos <= 0: + acq = min(float(s.buy_price) for s in slots if float(s.buy_price) >= 0) else: - acq = sum(float(slots[t].buy_price) * per_slot_wh for t in remaining) / total_wh + acq = sum(float(slots[t].buy_price) * per_slot_wh for t in pos_remaining) / total_wh_pos if abs(acq - acq_prev) < 0.05: break acq_prev = acq diff --git a/db/routines/R__063_fn_load_planning_slots_full.sql b/db/routines/R__063_fn_load_planning_slots_full.sql index 744f3a6..53d748b 100644 --- a/db/routines/R__063_fn_load_planning_slots_full.sql +++ b/db/routines/R__063_fn_load_planning_slots_full.sql @@ -584,11 +584,13 @@ begin sum(wk.buy_price * v_per_slot_charge_wh) filter ( where wk.allow_grid_charge + and wk.buy_price >= 0 and (v_first_neg_sell_ord is null or wk.slot_ord < v_first_neg_sell_ord) ) / nullif(sum(v_per_slot_charge_wh) filter ( where wk.allow_grid_charge + and wk.buy_price >= 0 and (v_first_neg_sell_ord is null or wk.slot_ord < v_first_neg_sell_ord) ), 0), v_ref_buy_czk_kwh @@ -952,6 +954,7 @@ begin coalesce(sum( case when wk.allow_grid_charge + and wk.buy_price >= 0 and ( v_acquisition_cutoff is null or wk.interval_start < v_acquisition_cutoff @@ -963,6 +966,7 @@ begin coalesce(sum( case when wk.allow_grid_charge + and wk.buy_price >= 0 and ( v_acquisition_cutoff is null or wk.interval_start < v_acquisition_cutoff @@ -974,6 +978,7 @@ begin min( case when wk.allow_grid_charge + and wk.buy_price >= 0 and ( v_acquisition_cutoff is null or wk.interval_start < v_acquisition_cutoff diff --git a/docs/05-todo.md b/docs/05-todo.md index bb7d5a7..22da870 100644 --- a/docs/05-todo.md +++ b/docs/05-todo.md @@ -28,6 +28,10 @@ Shrnutí otevřených bodů z `docs/06-open-questions.md`, checklistů v modulec |-------|-----|-----| | ~~**`charge_acquisition` po solve (two-pass):**~~ hotovo — `solve_dispatch_two_pass` v `planning_engine.py` (AUTO daily/rolling). | `planning_engine.py`, [`planning-arbitrage-accounting.md`](04-modules/planning-arbitrage-accounting.md) §6 | — | | ~~**Grid maska B (nejlevnější sloty):**~~ hotovo — `buy ASC` v AM/PM do Wh rozpočtu; cap z `ceil(budget/per_slot_wh)`. | `R__063` | — | +| **Self-konzistentní filtr B + acquisition bez `buy<0`:** iterativní filtr v `R__063` (v12); vážená acquisition pro filtr i `charge_acquisition_buy_czk_kwh` jen z `allow_grid_charge` s `buy>=0` (záporný OTE buy zůstává `allow_charge`, ale neřítí exportní marži). Two-pass `_recompute_charge_acquisition_from_results` také přeskočí `buy<0`. Ověřit po deploy: `two_pass_converged=true` na home-01. | `R__063`, `planning_engine.py` | programátor | +| **Večerní export plnou rychlostí v plánu:** Deye při peak sell často exportuje ~13 kW, ale LP někdy dá `grid_setpoint_w=-1` a jen část přes baterii → rozhozené toky vůči exekutorovi. Zvážit tvrdší `PEAK_EXPORT_SHORTFALL` / spodní mez `|grid+bať|` v `allow_discharge_export` slotech. | `planning_engine.py`, `docs/04-modules/planning.md` | programátor | +| **KV1 replan timeout (~120 s):** ruční/rolling replan občas spadne na timeout; 5. pokus prošel. Profilovat `fn_load_planning_slots_full` (iterativní filtr) + MILP délku horizontu; případně zkrátit horizont pro test nebo zvýšit limit API. | backend replan endpoint, APScheduler | programátor | +| **home-01 export při `sell<0` (26 slotů):** záměrně **ne** `block_export_on_negative_sell` (neriditelné PV B + zelený bonus). Plán stále může dávat `PV_SURPLUS` ~6–7 kW od ~10:30 když je SoC ~97 %+ — jiná osa než noční grid 4,8 Kč. Review ventilu `w_pv_b_vent_neg` / nabíjení před exportem, ne stejný fix jako KV1. | `planning_engine.py`, `planning-arbitrage-accounting.md` | programátor | --- diff --git a/docs/planning-changelog.md b/docs/planning-changelog.md index a99266e..86de1be 100644 --- a/docs/planning-changelog.md +++ b/docs/planning-changelog.md @@ -5,6 +5,16 @@ Formát: **datum (ISO)** · stručný důvod · soubory · chování / ověřen --- +## 2026-05-27 (b) — acquisition: vyloučit záporný OTE buy z váženého průměru + +**Problém (home-01 run 16588):** `two_pass_converged=false`, `acquisition_pass1≈−0.035` (pass1 nabíjení v `buy<0` slotech), `pass2≈0.88`. Noční grid 4,8 Kč už v plánu není (maska B OK), ale two-pass a arbitrážní marže exportu baterie byly křivé. + +**Oprava:** `R__063` — vážená acquisition ve filtru B a v `charge_acquisition_buy_czk_kwh` jen z `allow_grid_charge` s `buy_price >= 0`. `planning_engine._recompute_charge_acquisition_from_results` přeskočí `buy<0`. + +**Ověření:** po redeploy replan home-01 → `two_pass_converged=true`, `|acq1−acq2| < 0.05`. + +--- + ## 2026-05-27 — self-konzistentní grid maska B + ekonomický rozpad plánu (v12) **Problém (home-01, run 16522, tag v11):** Noční grid nabíjení (23:30–23:45, buy ~4,8 Kč) při `acquisition_pass1≈4,81` / `pass2≈0,84`, `two_pass_converged=false`; 26 slotů export při `sell<0`.