oprava vecerniho nevybijei
This commit is contained in:
@@ -4139,7 +4139,74 @@ class NegSellPrepWindowV36Tests(unittest.TestCase):
|
||||
day11_first = int(meta["days"][1]["first_neg_idx"])
|
||||
prev = _prague_calendar_date(slots[day11_first]) - timedelta(days=1)
|
||||
a11 = [(t, w) for t, w in anchors if _prague_calendar_date(slots[t]) == prev]
|
||||
self.assertEqual(len(a11), 1)
|
||||
self.assertGreaterEqual(len(a11), 1)
|
||||
|
||||
def test_evening_reserve_soc_near_reserve_after_discharge(self) -> None:
|
||||
"""v36d: capped slack + večerní ge_bat → SoC u kotvy ≤ reserve + max slack."""
|
||||
base = datetime(2026, 6, 10, 10, 0, tzinfo=ZoneInfo("Europe/Prague")).astimezone(
|
||||
timezone.utc
|
||||
)
|
||||
slots: list[PlanningSlot] = []
|
||||
for i in range(96):
|
||||
local = (base + timedelta(minutes=15 * i)).astimezone(
|
||||
ZoneInfo("Europe/Prague")
|
||||
)
|
||||
h = local.hour + local.minute / 60.0
|
||||
if local.date().day == 10:
|
||||
sell = 3.2
|
||||
else:
|
||||
sell = -0.2 if 9 <= h < 15 else 2.8
|
||||
slots.append(
|
||||
PlanningSlot(
|
||||
interval_start=base + timedelta(minutes=15 * i),
|
||||
buy_price=2.0,
|
||||
sell_price=sell,
|
||||
pv_a_forecast_w=4000,
|
||||
pv_b_forecast_w=5000,
|
||||
load_baseline_w=500,
|
||||
ev1_connected=False,
|
||||
ev2_connected=False,
|
||||
allow_charge=True,
|
||||
allow_discharge_export=True,
|
||||
)
|
||||
)
|
||||
bat = _battery(uc_wh=64_000.0, max_pct=95.0, arb_pct=20.0)
|
||||
bat.reserve_soc_wh = 0.20 * bat.usable_capacity_wh
|
||||
bat.planner_neg_sell_prep_soc_percent = 80.0
|
||||
bat.planner_neg_sell_full_soc_tail_slots = 4
|
||||
hp = SimpleNamespace(rated_heating_power_w=0, tuv_min_temp_c=45.0, tuv_target_temp_c=55.0)
|
||||
grid = SimpleNamespace(
|
||||
max_import_power_w=20_000,
|
||||
max_export_power_w=13_500,
|
||||
block_export_on_negative_sell=False,
|
||||
)
|
||||
vehicles = [
|
||||
SimpleNamespace(max_charge_power_w=0, battery_capacity_kwh=1.0, default_target_soc_pct=80.0),
|
||||
SimpleNamespace(max_charge_power_w=0, battery_capacity_kwh=1.0, default_target_soc_pct=80.0),
|
||||
]
|
||||
results, _, snap = solve_dispatch(
|
||||
slots,
|
||||
bat,
|
||||
hp,
|
||||
grid,
|
||||
[None, None],
|
||||
vehicles,
|
||||
0.55 * bat.soc_max_wh,
|
||||
50.0,
|
||||
operating_mode="AUTO",
|
||||
)
|
||||
self.assertEqual(snap.get("planner_build_tag"), "2026-05-28-neg-prep-window-v36d")
|
||||
anchors = snap["inputs"].get("neg_evening_reserve_soc_anchors") or []
|
||||
self.assertGreaterEqual(len(anchors), 1)
|
||||
anchor_iso = anchors[-1]["slot"]
|
||||
anchor_idx = next(
|
||||
i for i, s in enumerate(slots) if s.interval_start.isoformat() == anchor_iso
|
||||
)
|
||||
cap_wh = float(bat.reserve_soc_wh) + 400.0
|
||||
soc_wh = results[anchor_idx].battery_soc_target / 100.0 * bat.soc_max_wh
|
||||
self.assertLessEqual(soc_wh, cap_wh + 800.0)
|
||||
eve_slots = snap["inputs"].get("neg_evening_before_neg_slots") or []
|
||||
self.assertGreater(len(eve_slots), 8)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user