oprava KV 1
Some checks failed
CI and deploy / migration-check (push) Failing after 13s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-05-26 14:57:52 +02:00
parent 96b16b9ff9
commit 19108002ca
4 changed files with 110 additions and 12 deletions

View File

@@ -71,7 +71,7 @@ NEG_BUY_CHARGE_SHORTFALL_PENALTY_CZK_KWH = 100.0
PRE_NEG_CHARGE_PENALTY_CZK_KWH = 400.0
PRE_NEG_BATT_EXPORT_SHORTFALL_PENALTY_CZK_KWH = 80.0
PRE_NEG_BATT_EXPORT_MIN_SELL_CZK_KWH = 1.0
PLANNER_BUILD_TAG = "2026-05-28-neg-prep-window-v36d"
PLANNER_BUILD_TAG = "2026-05-28-neg-prep-window-v36e"
# Po t_detach v prep: necpát PV do bat (měkké; tvrdý hold přes soc_target z rampy).
NEG_SELL_POST_DETACH_BCPV_DISCOURAGE_CZK_KWH = 250.0
# Večer před neg dnem: výboj do sítě (měkký shortfall na ge_bat).
@@ -2047,6 +2047,20 @@ def solve_dispatch(
slots,
degrad_czk_kwh=float(degradation_cost_effective),
)
purchase_fixed_pre = _purchase_pricing_fixed(grid)
block_export_neg_sell_pre = bool(
getattr(grid, "block_export_on_negative_sell", False)
)
if purchase_fixed_pre and block_export_neg_sell_pre:
evening_peak_export_ts = sorted(
set(evening_peak_export_ts)
| {
t
for t, st in enumerate(slots)
if _in_night_battery_export_window(st)
and float(st.sell_price) > 0.0
}
)
non_negative_buys_pre = [
float(s.buy_price) for s in slots if float(s.buy_price) >= 0.0
]
@@ -2056,7 +2070,6 @@ def solve_dispatch(
else min(float(s.buy_price) for s in slots)
)
min_spread_pre = float(degradation_cost_effective)
purchase_fixed_pre = _purchase_pricing_fixed(grid)
fixed_tariff_like_pre = purchase_fixed_pre or _horizon_fixed_tariff_like(slots)
neg_sell_phases_en = (
om == "AUTO"
@@ -2153,6 +2166,14 @@ def solve_dispatch(
fixed_tariff=fixed_tariff_like_pre,
):
profitable_export_ts_pre.add(_t)
elif (
purchase_fixed_pre
and block_export_neg_sell_pre
and _t in evening_peak_export_ts
and float(slots[_t].sell_price) > 0.0
):
# KV1: večerní sell může být < fixní buy; peak sloty stejně vývoz bat.
profitable_export_ts_pre.add(_t)
evening_push_ts: set[int] = set()
evening_early_export_penalty_ts: set[int] = set()
if om == "AUTO":
@@ -3287,11 +3308,18 @@ def solve_dispatch(
or t < first_neg_buy_idx
)
) or (
# Spot (home-01, KV1): při sell>=0 neblokovat ge_pv — solver export vs bc_pv;
# šetření na večerní peak = ge_bat, ne curtail FVE (pv_store jen sell<0 / fixed).
# Spot: při sell>=0 neblokovat ge_pv (export vs bc_pv; večerní peak = ge_bat).
not purchase_fixed_pre
and sell_t >= 0
and pv_surplus_w > 500
) or (
# KV1 (fixed + block_export, jen PV A): bez pole B neplatí fixed_pv_b_export_cap;
# jinak ge_pv==0 → plný curtail při plné baterii místo prodeje do site.
purchase_fixed_pre
and bool(getattr(grid, "block_export_on_negative_sell", False))
and float(s.pv_b_forecast_w) <= 0.0
and sell_t >= 0.0
and pv_surplus_w > 500
)
# BA81: export pole B jen při kladném sell (po sell<0 jinak ge==0 výše).
fixed_pv_b_export_cap = (