dalsi rozvolneni at vic jedeme arbitraz
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-21 14:54:46 +02:00
parent 3b4d54dcc7
commit 66834ddfa6
3 changed files with 51 additions and 17 deletions

View File

@@ -14,7 +14,7 @@ Discharge-export mask:
from __future__ import annotations
import unittest
from datetime import datetime, timezone, timedelta
from datetime import date, datetime, timezone, timedelta
from types import SimpleNamespace
from zoneinfo import ZoneInfo
@@ -27,6 +27,24 @@ _BUY_CHARGE_BAND = 0.40
_MAX_GRID_CHARGE_CAP = 24
def _prague_date(s: PlanningSlot) -> date:
return s.interval_start.astimezone(_PRAGUE).date()
def _export_window_start(slots: list[PlanningSlot], degrad: float) -> datetime | None:
"""Kopie R__063: sell > min(buy) téhož kalendářního dne (Prague) + degrad."""
result: datetime | None = None
for s in slots:
day = _prague_date(s)
day_min = min(
float(x.buy_price) for x in slots if _prague_date(x) == day
)
if float(s.sell_price) > day_min + degrad:
if result is None or s.interval_start < result:
result = s.interval_start
return result
def _future_sell(slots: list[PlanningSlot], t: int) -> float:
tail = [float(slots[i].sell_price) for i in range(t + 1, len(slots))]
return max(tail) if tail else float(slots[t].sell_price)
@@ -82,11 +100,8 @@ def _select_charge_slots(
default=min(float(s.buy_price) for s in slots),
)
ref_buy_global = min(float(s.buy_price) for s in slots)
export_window_start: datetime | None = None
for s in slots:
if float(s.sell_price) > ref_buy_global + degrad:
if export_window_start is None or s.interval_start < export_window_start:
export_window_start = s.interval_start
export_window_start = _export_window_start(slots, degrad)
plan_day = _prague_date(slots[0])
eta = float(getattr(battery, "charge_efficiency", 1.0) or 1.0)
max_p_w = float(getattr(battery, "max_charge_power_w", 0.0) or 0.0)
@@ -135,13 +150,15 @@ def _select_charge_slots(
return False
return True
def _grid_sort_key(t: int, pred: bool, price: float) -> tuple[int, int, float, int]:
before_export = 0
if export_window_start is not None and slots[t].interval_start < export_window_start:
before_export = 0
else:
before_export = 1
return (before_export, int(pred), price, t)
def _grid_sort_key(t: int, pred: bool, price: float) -> tuple[int, int, int, float, int]:
today_first = 0 if _prague_date(slots[t]) == plan_day else 1
before_export = (
0
if export_window_start is not None
and slots[t].interval_start < export_window_start
else 1
)
return (today_first, before_export, int(pred), price, t)
if purchase_pricing_mode != "fixed":
am_candidates = [