dalsi fix
This commit is contained in:
@@ -3615,6 +3615,88 @@ class ChargeAcquisitionArbitrageTests(unittest.TestCase):
|
||||
self.assertFalse(snap_mid["inputs"].get("neg_sell_phases_fallback"))
|
||||
self.assertLess(results_mid[0].grid_setpoint_w, -1000)
|
||||
|
||||
def test_home01_late_replan_high_soc_realistic_masks(self) -> None:
|
||||
"""Pozdní replan večer (21:00): SoC ~74 %, SQL masky allow_charge=false večer — musí být Feasible."""
|
||||
prague = ZoneInfo("Europe/Prague")
|
||||
base = datetime(2026, 6, 6, 21, 0, tzinfo=prague).astimezone(timezone.utc)
|
||||
rows = [
|
||||
(5.305729, 3.34, 2731, 0, 0),
|
||||
(5.162299, 3.23125, 2731, 0, 0),
|
||||
(4.866865, 3.00725, 2731, 0, 0),
|
||||
(4.662765, 2.8525, 2731, 0, 0),
|
||||
(5.18406, 3.24775, 1552, 0, 0),
|
||||
(4.878076, 3.01575, 1552, 0, 0),
|
||||
(4.749483, 2.91825, 1552, 0, 0),
|
||||
(4.460314, 2.699, 1552, 0, 0),
|
||||
(4.887308, 3.02275, 782, 0, 0),
|
||||
(4.883351, 3.01975, 782, 0, 0),
|
||||
(4.660787, 2.851, 782, 0, 0),
|
||||
(4.484384, 2.71725, 782, 0, 0),
|
||||
]
|
||||
slots: list[PlanningSlot] = []
|
||||
for i in range(96):
|
||||
local = (base + timedelta(minutes=15 * i)).astimezone(prague)
|
||||
if i < len(rows):
|
||||
buy, sell, load, pv_a, pv_b = rows[i]
|
||||
else:
|
||||
d, h, m = local.day, local.hour, local.minute
|
||||
hm = h + m / 60.0
|
||||
if d == 6:
|
||||
buy, sell, load, pv_a, pv_b = 4.5, 2.9, 800, 0, 0
|
||||
elif hm >= 5.75 and hm < 15:
|
||||
sell, buy = -0.3, 0.5
|
||||
pv_a, pv_b, load = 2000, 2500, 800
|
||||
elif 11 <= hm < 14:
|
||||
sell, buy = -0.8, -0.4
|
||||
pv_a, pv_b, load = 4000, 4500, 2000
|
||||
else:
|
||||
sell, buy = 2.5, 3.0
|
||||
pv_a, pv_b, load = 200, 200, 500
|
||||
pv_surplus = max(0, pv_a + pv_b - load)
|
||||
h = local.hour
|
||||
allow_discharge_export = sell >= 0 and (h >= 17 or sell > buy + 0.15)
|
||||
allow_charge = buy < 0 or (sell < 0 and pv_surplus > 500)
|
||||
slots.append(
|
||||
PlanningSlot(
|
||||
interval_start=base + timedelta(minutes=15 * i),
|
||||
buy_price=buy,
|
||||
sell_price=sell,
|
||||
pv_a_forecast_w=pv_a,
|
||||
pv_b_forecast_w=pv_b,
|
||||
load_baseline_w=load,
|
||||
ev1_connected=False,
|
||||
ev2_connected=False,
|
||||
allow_charge=allow_charge,
|
||||
allow_discharge_export=allow_discharge_export,
|
||||
)
|
||||
)
|
||||
bat = _battery(uc_wh=64_000.0, arb_pct=20.0, terminal_soc_value_factor=0.9)
|
||||
bat.planner_neg_sell_prep_soc_percent = 80
|
||||
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=17_000,
|
||||
max_export_power_w=13_500,
|
||||
block_export_on_negative_sell=False,
|
||||
purchase_pricing_mode="spot",
|
||||
)
|
||||
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, _ms, snap = solve_dispatch_two_pass(
|
||||
slots,
|
||||
bat,
|
||||
hp,
|
||||
grid,
|
||||
[None, None],
|
||||
vehicles,
|
||||
0.74 * bat.soc_max_wh,
|
||||
50.0,
|
||||
operating_mode="AUTO",
|
||||
)
|
||||
self.assertLess(results[0].grid_setpoint_w, -500)
|
||||
self.assertLess(results[0].battery_soc_target, 70.0)
|
||||
|
||||
def test_kv1_evening_push_profitable_vs_morning_zone_peak(self) -> None:
|
||||
"""v52: KV1 večer ≥ ranní max (5–11) − degrad; pod prahem ne."""
|
||||
prague = ZoneInfo("Europe/Prague")
|
||||
|
||||
Reference in New Issue
Block a user