v2: PV-risk front-load — nabít v neg okně co nejdřív (nejistota predikce)
All checks were successful
CI and deploy / migration-check (push) Successful in 29s
CI and deploy / deploy (push) Successful in 1m0s

v1 to řešil rampou (plný výkon než se řeže pole A — zelený bonus B, riziko
večerního mraku). v2 byl k načasování v okně sell<0 indiferentní (PV zdarma
kdykoliv) a směl nabíjení odložit — odklad ale spoléhá na predikci.

Mechanismus: malá prémie za držení energie dřív (objective −= soc[t] ×
frontload v neg slotech). Rozbíjí indiferenci směrem k front-loadu, nikdy
nepřebije skutečné ceny. Velikost z DB: asset_battery.
planner_pv_risk_frontload_czk_kwh (V090, default 0.01; 0 = vypnuto),
přes fn_planning_site_context (R__039). Test: 4 sloty plným tempem od startu.
Eval fixtures beze změny (sloupec v nich není → 0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dusan Vojacek
2026-06-12 09:55:22 +02:00
parent e464b114b9
commit 2932d48080
5 changed files with 44 additions and 1 deletions

View File

@@ -22,6 +22,10 @@
# z DB (planner_night_baseload_buffer_percent → slot.night_baseload_buffer_wh,
# klesá k 0 do rána); porušení je PLACENÉ cenou buy daného slotu (riziko
# zpětného nákupu), takže extrémní sell špička ho smí racionálně prodat.
# - PV-risk front-load: v okně sell<0 je nabíjení z PV zdarma kdykoliv →
# indiference v čase; odložení ale spoléhá na predikci (večerní mrak).
# Malá prémie za držení energie dřív (DB planner_pv_risk_frontload_czk_kwh)
# vede k "nabít plným výkonem hned, pak řezat A" — emergentně, bez rampy.
#
# Vědomé odchylky od v1 (změří harness):
# - SQL masky allow_charge / allow_discharge_export se IGNORUJÍ (jsou to
@@ -307,6 +311,11 @@ def solve_dispatch_v2(
]
if nb_terms:
extras += pulp.lpSum(nb_terms)
frontload = float(getattr(battery, "planner_pv_risk_frontload_czk_kwh", 0.0) or 0.0)
neg_idx = [t for t in range(T) if float(slots[t].sell_price) < 0.0]
if frontload > 0 and neg_idx:
# odměna za soc[t] v neg slotech = dřívější nabití vyhrává při indiferenci
extras -= pulp.lpSum(soc[t] / 1000.0 * frontload for t in neg_idx)
prob += cash + degradation + extras - terminal * soc[T - 1]
@@ -408,6 +417,7 @@ def solve_dispatch_v2(
"ev_sessions": sum(1 for x in ev_sessions if x is not None),
"masks_ignored": True,
"night_buffer_slots": sum(1 for b in nb_buffer_wh if b > 0),
"pv_risk_frontload_czk_kwh": frontload if neg_idx else 0.0,
"night_buffer_max_wh": round(max(nb_buffer_wh), 1) if nb_buffer_wh else 0,
},
"objective_terms": {